6

I need to unit testing this GetData method.

    public MessageResponse GetData(XmlElement requestElement)
    {   
        MessageResponse MsgResponse = new MessageResponse();


        if (requestElement.Attributes["employeeNo"] == null){
            MsgResponse.Messages = new List<string>();
            MsgResponse.Messages.Add("Attribute employeeNo is missing");
            MsgResponse.Error = true;
            return MsgResponse;
        }
        if (requestElement.Attributes["xmlEmployeeName"] == null){
            MsgResponse.Messages.Add("Attribute xmlEmployeeName is missing");
            MsgResponse.Error = true;
            return MsgResponse;
        }
        return MsgResponse;
    }

this method needs a XmlElement parameter. how do I mock it? in my code, I first created a xmlDocument, then load the xml file.

            XmlDocument doc = new XmlDocument();
            doc.Load(xmlFilePath);
            requestElement = doc.DocumentElement;

for me to test it, first i need to create a xml file without employeeNo, the create antoher one without name, maybe alot more for other scenarios. it just seems like alot work. is there a better way to test it?

should I use moq or other testing framework to simplify the testing?

4

3 回答 3

9

您可以只创建要测试的元素,而无需读取文件:

var doc = new XmlDocument();
doc.LoadXml("<MyTestElement/>");
var myTestElement = doc.DocumentElement;
myTestElement.Attributes["employeeNo"] = "fakeId";

var response = myTestResponder.GetData(myTestElement);

//assert whatever you need to

注意:每次你发现测试太难写时,通常这意味着你的类/方法做得太多。

我会假设,您的方法会验证输入,而不是对提供的数据进行验证。我建议您抽象数据读取部分(使用一些 xml 反序列化器)来填充您的应用程序所需的数据模型。

然后对反序列化数据的结果运行验证。就像是:

public MessageResponse GetData(XmlElement requestElement)
{
   var data = _xmlDeserializer.Deserialize(requestElement);
   var validationResult = _validator.Validate(data);
    if (validationResult.Errors.Count > 0)
    {
         //populate errors
        return result;
    }

    _dataProcessor.DoSomethingWithData(data);
}

查看FluentValidation以获得一个不错的验证库。

如果你走上述路线,那么你的测试会简单得多。

于 2013-11-01T18:50:06.277 回答
1
[TestMethod]
public void GetData_Returns_Correct_Message_When_EmployeeNo_Is_Null()
{
    var inputWithoutEmployeeNo = GetElement(@"<input></input>");

    var actual = GetData(inputWithoutEmployeeNo);

    Assert.IsTrue(actual.Error, "Error should be true when employee no. is missing");
    Assert.IsNotNull(actual.Messages);
    Assert.AreEqual(1, actual.Messages.Count);
    Assert.AreEqual("Attribute employeeNo is missing", actual.Messages[0]);
}

private XmlElement GetElement(string xml)
{
    var doc = new XmlDocument();
    doc.LoadXml(xml);
    return doc.DocumentElement;
}

在进行单元测试时,我发现代码抛出了 NullReferenceException。以下单元测试演示了该问题:

[TestMethod]
[ExpectedException(typeof(NullReferenceException))]
public void GetData_Throws_NullReferenceException_When_EmployeeNo_Is_Not_Null_And_XmlEmployeeName_Is_Null()
{
    var inputWithoutEmployeeNo = GetElement(@"<input employeeNo='123'></input>");

    GetData(inputWithoutEmployeeNo);
}
于 2013-11-01T18:58:35.907 回答
0

使用起订量

using System;
using System.Xml;
using Moq;
using NUnit.Framework;

namespace MockXmlTest
{
    [TestFixture]
    public class MyServiceTests
    {
        private MockSetup _mockSetup;
        [SetUp]
        public void Init()
        {
            _mockSetup = MockSetup.HappySetup();
        }
        [Test]
        public void MyService_Should_Return_Guid()
        {
            //Arrange
            var myService = _mockSetup.MyService.Object;
            var id = 42;
            var expected = Guid.Empty.ToString();

            //Act
            var actual = myService.GetXml(id);

            //Assert
            Assert.AreEqual(expected, actual.FirstChild.InnerText);
        }
    }

    public class MyService : IMyService
    {
        public XmlDocument GetXml(int id)
        {
            var doc = new XmlDocument();
            //Do real stuff
            return doc;
        }
    }

    public interface IMyService
    {
        XmlDocument GetXml(int id);
    }

    public class MockSetup
    {
        public Mock<IMyService> MyService { get; set; }

        public MockSetup()
        {
            MyService = new Mock<IMyService>();
        }
        public static MockSetup HappySetup()
        {
            var mockSetup = new MockSetup();

            var mockDoc = CreateMockDoc();

            //Matches any id of an integer, returns a XmlDocument mock
            mockSetup.MyService.Setup(m => m.GetXml(It.IsAny<int>())).Returns(mockDoc);
            return mockSetup;
        }

        private static XmlDocument CreateMockDoc()
        {
            //<Main><MyGuid>00000000-0000-0000-0000-000000000000</MyGuid></Main>
            XmlDocument mockDoc = new XmlDocument();
            XmlElement el = (XmlElement)mockDoc.AppendChild(mockDoc.CreateElement("Main"));

            el.AppendChild(mockDoc.CreateElement("MyGuid")).InnerText = It.IsAny<Guid>().ToString();
            return mockDoc;
        }
    }
}
于 2020-01-24T20:54:59.447 回答