I am creating some unit tests for a controller I have however I ran into a problem.
Basically I have the following:-
The Controller Method :-
[ResponseType(typeof(Attrib))]
public IHttpActionResult GetAttrib(int id)
{
var attrib = _attribsRepository.GetAttrib(id);
if (attrib == null)
{
return NotFound();
}
return Ok(attrib);
}
Its a simple Web API 2.0 method.
Then I have the Repository :-
public Attrib GetAttrib(int id)
{
return DbSet.FirstOrDefault(x=>x.Id == id);
}
And finally the Test Method:-
public class AttribsControllerTests
{
public Mock<IAttribsRepository> _attribsRepositoryMock;
public List<Attrib> AttribList;
public AttribsController AttribsController;
[SetUp]
public void Init()
{
_attribsRepositoryMock = new Mock<IAttribsRepository>();
AttribList = new List<Attrib>
{
new Attrib()
{
Id = 1,
AttributeId = "Cro",
AttributeName = "Crossing",
AttributeType = "Tech",
AttributeValue = 1
},
new Attrib()
{
Id = 2,
AttributeId = "Dri",
AttributeName = "Dribbling",
AttributeType = "Tech",
AttributeValue = 2
},
new Attrib()
{
Id = 3,
AttributeId = "Fin",
AttributeName = "Finishing",
AttributeType = "Tech",
AttributeValue = 3
}
};
}
[Test]
public void Get_Check_That_Id1_Returns_Crossing()
{
//Arrange
_attribsRepositoryMock.Setup(t => t.GetStaticAttribs()).Returns(AttribList.AsQueryable());
//Act
var attribsController = new AttribsController(_attribsRepositoryMock.Object);
var result = attribsController.GetAttrib(1) as OkNegotiatedContentResult<Attrib>;
//Assert
Assert.IsNotNull(result);
Assert.AreEqual(AttribList[0].AttributeName, "Cor");
}
}
For some reason, the result is always null, so its not hitting the controller correctly.
Any ideas why this could happen? When debugging, the correct Mock Repository is hitting the controller, and it should have the 3 entries in it.
Any help will be very much appreciated.
You setup GetStaticAttribs but it is used nowhere in the example you showed. You were suppose to setup IAttribsRepository.GetAttrib
Based on your example
[Test]
public void Get_Check_That_Id1_Returns_Crossing() {
//Arrange
var id = 1;
_attribsRepositoryMock.Setup(t => t.GetAttrib(id)).Returns(AttribList[0]);
var attribsController = new AttribsController(_attribsRepositoryMock.Object);
//Act
var result = attribsController.GetAttrib(id) as OkNegotiatedContentResult<Attrib>;
//Assert
Assert.IsNotNull(result);
Assert.IsNotNull(result.Content);
Assert.AreEqual(result.Content.AttributeName, "Crossing");
}
Related
public class UserService
{
IUserRepo userRepo;
UserService(IUserRepo repo)
{
userRepo = repo;
}
void AddUser(JsonData data)
{
User user = new User()
{
Name = data.name,
Number = data.Number
};
userRepo.Insert(user);
int id = user.id;
}
}
id is 0 when a unit test case is debugged, but when it is a proper call it returns proper primary key i.e. 1, 2, 3, etc.
Mock
class TestCases
{
Mock<IUserRepo> mockUserRepo = new Mock<IUserRepo>();
[Test]
public void test1()
{
//Arrange
JsonData obj = new JsonData()
{
Name = "Jane",
Number = "0563722992"
}
User dumpUser= new User()
{
Name = "Def",
Number = "8111"
};
mockUserRepo
.Setup(x => x.Insert(It.IsAny<User>()))
.Callback(() => dumpUser.Id = 1);
//Act
UserService u = new UserService(mockUserRepo.Object);
u.AddUser(obj);
//Assert
}
}
While debugging the unit test it seems that callback is unable to change the id to 1 when it passes through the method Insert().
Can anybody help how to tackle with this issue?
There is no need for
User dumpUser= new User()
{
Name = "Def",
Number = "8111"
};
As the method under test creates/initializes it's own instance within.
Capture the passed argument in the call back and update the desired member there
//...
userRepo
.Setup(x => x.Insert(It.IsAny<User>()))
.Callback((User arg) => arg.Id = 1);
//...
I am attempting to write a unit test for this method:
public List<Annotation> GetNotesByOrderGuid(Guid orderGuid)
{
var result = _xrmServiceContext.SalesOrderSet.Where(x => x.Id == orderGuid); //!!!!! this is returning correctly 1 record, however, it shows NULL for the list of annotations
//do some stuff and return a list of annotations
}
My unit test creates 2 notes, and attaches them to the sales order:
private XrmFakedContext _fakeContext;
[NotNull]
private IOrganizationService _fakeOrganizationService;
[Test]
public void GetNotesByOrderGuid_ExistingRecordHavingNotes_ReturnsListOfThoseNotes()
{
using (var xrmServiceContext = new XrmServiceContext(_fakeOrganizationService))
{
// Arrange
var salesOrderGuid = Guid.NewGuid();
var salesOrder = new SalesOrder { Id = salesOrderGuid };
var note1 = new Annotation
{
Id = Guid.NewGuid(),
NoteText = "this is note1",
ObjectId = new EntityReference(SalesOrder.EntityLogicalName, salesOrderGuid),
ObjectTypeCode = salesOrder.LogicalName
};
var note2 = new Annotation
{
Id = Guid.NewGuid(),
NoteText = "this is note2",
ObjectId = new EntityReference(SalesOrder.EntityLogicalName, salesOrderGuid),
ObjectTypeCode = salesOrder.LogicalName
};
_fakeContext.Initialize(new List<Entity> { salesOrder, note1, note2});
var sut = new SalesOrderService(xrmServiceContext);
// Act
// Assert
Assert.That(sut.GetNotesByOrderGuid(salesOrderGuid), Is.InstanceOf<List<Annotation>>());
}
}
[SetUp]
public void Init()
{
_fakeContext = new XrmFakedContext { ProxyTypesAssembly = Assembly.GetAssembly(typeof(SalesOrder)) };
_fakeOrganizationService = _fakeContext.GetFakedOrganizationService();
}
What am doing incorrectly in adding annotations to my entity?
The reason I ask is because when the unit tests runs this code:
var result = _xrmServiceContext.SalesOrderSet.Where(x => x.Id == orderGuid);
it shows that although there is 1 result, as there correctly should be; it shows that no annotations have been linked to it:
I have this test method for testing an API controller, that returns a JSON string, for a non null response.
[TestClass]
public class TransactionsTests
{
[TestMethod]
public void ColorPerformance_GetChartData_NotNullResponse_Test()
{
// Arrange
string quality = null, cars = null, year = "2015";
var listColorPerformanceChartData = new List<ColorPerformanceChartData>();
var mockRepository = new Mock<IColorPerformanceRepository>();
mockRepository.Setup(x => x.GetChartData(quality, cars, year))
.Returns(listColorPerformanceChartData);
var controller = new ColorPerformanceController(mockRepository.Object);
// Act
IHttpActionResult actionResult = controller.GetChartData(quality, cars, year);
var contentResult = actionResult as OkNegotiatedContentResult<object>;
// Assert
Assert.IsNotNull(contentResult);
Assert.IsNotNull(contentResult.Content);
}
}
This test is passing in that contentResult is not null. However, I am not feeling sure that the test is written properly for the following reasons:
contentResult.Content has empty data, in that there is no data being returned from _repository.GetChartData() method, but is not empty because still the json constructed is as follows:
{ categories = {int[0]}, series = { name = "Number of colors", data = {double[0]} } }
contentResult.ContentNegotiator, contentResult.Formatter and contentResult.Request all are throwing an exception of InvalidOperationException with the message HttpControllerContext.Configuration must not be null. I don't know why this is happening.
The API Controller:
public class ColorPerformanceController : ApiController
{
private IColorPerformanceRepository _repository;
public ColorPerformanceController(IColorPerformanceRepository repository)
{
_repository = repository;
}
public IHttpActionResult GetChartData(string quality, string cars, string year)
{
try
{
var data = ProcessData(quality, cars, year);
return Ok(data);
}
catch (Exception ex)
{
return InternalServerError(ex);
}
}
private object ProcessData(string quality, string cars, string year)
{
var data = _repository.GetChartData(quality, cars, year);
return new {
categories = data.Select(d => d.Id).ToArray(),
series = new[] { new { name = "Number of colors", data = data.Select(d => d.CumulativePercentage).ToArray() }}
};
}
}
IColorPerformanceRepository:
public interface IColorPerformanceRepository
{
IEnumerable<ColorPerformanceChartData> GetChartData(string quality, string cars, string year);
}
The object returned from the repository implementation:
public class ColorPerformanceChartData
{
private double _cumulativePercentage;
public double CumulativePercentage {
get { return Math.Round(_cumulativePercentage, 2); }
set { _cumulativePercentage = value; }
}
public int Id { get; set; }
}
What am I missing or doing wrong here?
Best practice is you should avoid using anonymous type in this case:
private object ProcessData(string quality, string cars, string year)
{
var data = _repository.GetChartData(quality, cars, year);
return new {
categories = data.Select(d => d.Id).ToArray(),
series = new[] { new { name = "Number of colors", data = data.Select(d => d.CumulativePercentage).ToArray() }}
};
}
Try defining a class for it so that you can de-serialize the string and check each property:
// Act
IHttpActionResult actionResult = controller.GetChartData(quality, cars, year);
//Notice I use YourClass instead of object here.
var contentResult = actionResult as OkNegotiatedContentResult<YourClass>;
// Assert
Assert.IsNotNull(contentResult);
Assert.IsNotNull(contentResult.Content);
//Assert all properties of contentResult.Content like categories, series,..
Regarding the exception, try:
var controller = new ColorPerformanceController(mockRepository.Object);
//Add these 2 lines
controller.Request = new HttpRequestMessage();
controller.Configuration = new HttpConfiguration();
From http://www.asp.net/web-api/overview/testing-and-debugging/unit-testing-controllers-in-web-api
I have the following three methods in the CompanyApplication class (along with the supporting factories and services listed):
public ResultSet<CompanyDto> AddCompany(CompanyDto companyDto)
{
var result = new CompanyDto();
var company = new Company();
Mapper.Map(companyDto, company);
using (ITransaction t = _transactionFactory.Create())
{
company = _companyService.Add(company);
t.Commit();
}
Mapper.Map(company, result);
return new ResultSet<CompanyDto>(1, new[] { result });
}
public ResultSet<CompanyContactDto> AddCompanyContact(CompanyContactDto companyContactDto)
{
var result = new CompanyContactDto();
var company = new Company();
var contact = new CompanyContact();
Mapper.Map(companyContactDto, contact);
using (ITransaction t = _transactionFactory.Create())
{
var contactCompanies = FindByIdJoin<Company, CompanyDto>(companyContactDto.CompanySK);
Mapper.Map(contactCompanies.Data.First(), company);
company.CompanyContacts.Add(contact);
company = _companyService.Update(company);
t.Commit();
}
Mapper.Map(contact, result);
return new ResultSet<CompanyContactDto>(1, new[] { result });
}
public ResultSet<T_DtoType> FindByIdJoin<T_DbType, T_DtoType>(long id)
{
IAbstractRepository<T_DbType> repository = EnsureRepository<T_DbType>();
T_DbType entity = repository.FindByIdJoin(id);
return (entity == null ? null : MapResultSetToDto<T_DbType, T_DtoType>(entity));
}
There are other objects in play here, which is why the FindByIdJoin has been made a separate method in the CompanyApplication class.
I have set up the testing class with some mocks and an instance of the CompanyApplication class:
private Mock<ICompanyRepository> _mockCompanyRepository;
private Mock<ICompanyDomain> _mockCompanyService;
private Mock<ITransactionFactory> _mockTransactionFactory;
private Mock<ITransaction> _mockTransaction;
private CompanyApplication _companyApplication;
[Setup]
public void SetUp()
{
_mockCompanyRepository = new Mock<ICompanyRepository>(MockBehavior.Strict);
_mockCompanyService = new Mock<ICompanyDomain>(MockBehavior.Strict);
_mockTransactionFactory = new Mock<ITransactionFactory>(MockBehavior.Strict);
_mockTransaction = new Mock<ITransaction>(MockBehavior.Strict);
_companyApplication = new CompanyApplication(
_mockCompanyRepository.Object,
_mockCompanyService.Object,
_mockTransactionFactory.Object);
}
I am successfully able to test the FindByIdJoin and AddCompany methods directly in Moq like this:
[Test]
public void CanFindCompanyByIdJoin()
{
var data = new Company {ObjectId = 1, Name = "Company1"};
_mockCompanyRepository.Setup(x => x.FindByIdJoin(It.Is<long>(arg => arg == data.ObjectId)))
.Returns(data);
var result = _companyApplication.FindByIdJoin<Company, CompanyDto>(data.ObjectId);
Assert.AreEqual(data.ObjectId, result.Data.First().ObjectId);
}
[Test]
public void CanAddCompany()
{
var data = new Company {ObjectId = 1, Name = "Company1"};
_mockCompanyService.Setup(x => x.Add(It.Is<Company>(arg => arg.ObjectId == data.ObjectId)))
.Returns(data);
_mockTransactionFactory.Setup(x => x.Create()).Returns(_mockTransaction.Object);
_mockTransaction.Setup(x => x.Commit());
_mockTransaction.Setup(x => x.Dispose());
var dto = new CompanyDto {ObjectId = 1, Name = "Company1"};
var result = _companyApplication.AddCompany(dto);
_mockCompanyService.Verify(t => t.Add(It.IsAny<Company>()));
}
Those two tests pass just fine. However, I'm having trouble coming up with a test for AddCompanyContact, because it calls FindByIdJoin as part of its flow, and that seems to be getting in the way.
Specifically, is there a way to mock var contactCompanies = FindByIdJoin<Company, CompanyDto>(companyContactDto.CompanySK) in a test for the AddCompanyContact method?
Thanks!
There is two alternatives that i see depending on the amount of work that you want to do.
Wrap that call into a object and instantiate it using a IOC container. This is the one that i feel would take the most effort if you are not using one already.
Turn that call into a Func and make a method without that parameter that does the call. This approach has the disadvantage that the top call will be untestable but will allow access to the rest of the method.
Example Below:
public ResultSet<CompanyContactDto> AddCompanyContact(CompanyContactDto companyContactDto)
{
AddCompanyContact(CompanyContactDto, ()=>
{
return FindByIdJoin<Company, CompanyDto> companyContactDto.CompanySK);
}
}
public ResultSet<CompanyContactDto> AddCompanyContact(CompanyContactDto companyContactDto, Func<WhateverTheMethodReturns> findIdReplacement)
{
var result = new CompanyContactDto();
var company = new Company();
var contact = new CompanyContact();
Mapper.Map(companyContactDto, contact);
using (ITransaction t = _transactionFactory.Create())
{
var contactCompanies = findIdReplacement();
Mapper.Map(contactCompanies.Data.First(), company);
company.CompanyContacts.Add(contact);
company = _companyService.Update(company);
t.Commit();
}
Mapper.Map(contact, result);
return new ResultSet<CompanyContactDto>(1, new[] { result });
}
I was over complicating the problem... since AddCompanyContact calls FindByIdJoin, all I needed to do was mock the same interface that is used in FindByIdJoin.
Lesson learned: mock interfaces, not classes.
I have the following code:
var connector = new Mock<IConector>();
connector
.Setup(cn => cn.listar("FetchEstandar", new Estandar(), new {Id = 1}))
.Returns(new List<Estandar>{ new Estandar {Id = 1} });
var entidad = connector.Object
.listar("FetchEstandar", new Estandar(), new {Id = 1});
when I call listar on the connector Object, I get an "Expression Cannot Contain an Anonymouse Type" error. I've tried with rhino mocks and moq.
Is there any way I can mock this method? am I doing something wrong? alternatively, I could ignore this parameter but I don't know how. I really just need to test the value of the first parameter and ignorearguments works but I have no idea whether or how I can get this value if I use it
I do not know if this is the only way to match an anonymous object but it can be done using It.Is<>() and reflection
public class Estandar {
public int Id { get; set; }
}
public interface IConector {
IEnumerable<Estandar> listar(string name, Estandar estandar, object key);
}
[TestMethod]
public void CheckAnonymous() {
var connector = new Mock<IConector>();
connector.Setup(cn => cn.listar("FetchEstandar",
It.IsAny<Estandar>(),
It.Is<object>(it => MatchKey(it, 1))))
.Returns(new List<Estandar> { new Estandar { Id = 1 } });
var entidad = connector.Object.listar("FetchEstandar", new Estandar(), new { Id = 1 });
Assert.AreEqual(1, entidad.Count());
}
public static bool MatchKey(object key, int soughtId) {
var ret = false;
var prop = key.GetType().GetProperty("Id");
if (prop != null) {
var id = (int)prop.GetValue(key, null);
ret = id == soughtId;
}
return ret;
}