Как вы издеваетесь над XML для модульного тестирования?
Мне нужно модульное тестирование этого метода GetData.
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;
}
этот метод нуждается в параметре XmlElement. как я высмеиваю это? в своем коде я сначала создал xmlDocument, а затем загрузил файл xml.
XmlDocument doc = new XmlDocument();
doc.Load(xmlFilePath);
requestElement = doc.DocumentElement;
для меня, чтобы проверить это, сначала мне нужно создать XML-файл без employeeNo, создать еще один без имени, может быть, много больше для других сценариев. это просто кажется много работы. Есть ли лучший способ проверить это?
я должен использовать moq или другую среду тестирования, чтобы упростить тестирование?
2 ответа
Вы можете просто создать элемент, с которым хотите протестировать, вообще не читая файл:
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 для хорошей библиотеки проверки.
Если вы пойдете по вышеуказанному маршруту, то ваши тесты будут намного проще.
[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);
}
Использование Moq
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;
}
}
}