I'm using the moq framework by Daniel Cazzulino, kzu Version 4.10.1.
I want to moq so i can test a particular part of functionality (below is the simplistic version of the Code i could extract)
The fluent/chain method so are designed so you can get object by an Id and include any additional information if required.
i'm having some trouble fetching the correct object when the function is calling the moq'ed method, which is currently returning the last moq'ed object which is wrong
/*My current Moq setup*/
class Program
{
static void Main(string[] args)
{
var mock = new Mock<IFluent>();
var c1 = new ClassA() { Id = 1, Records = new List<int>() { 5, 2, 1, 10 }, MetaData = new List<string>() };
var c2 = new ClassA() { Id = 2, Records = new List<int>(), MetaData = new List<string>() { "X", "Y", "Z" } };
mock.Setup(x => x.GetById(1).IncludeRecords().IncludeMetaData().Get()).Returns (c1);
mock.Setup(x => x.GetById(2).IncludeRecords().IncludeMetaData().Get()).Returns(c2);
var result = new ComputeClass().ComputeStuff(mock.Object);
Console.WriteLine(result);
Console.ReadLine();
}
}
/*Fluent interface and object returned*/
public interface IFluent
{
IFluent GetById(int id);
IFluent IncludeRecords();
IFluent IncludeMetaData();
ClassA Get();
}
public class ClassA
{
public int Id { get; set; }
public ICollection<int> Records { get; set; }
public ICollection<string> MetaData { get; set; }
}
/*the method which is doing the work*/
public class ComputeClass
{
public string ComputeStuff(IFluent fluent)
{
var ids = new List<int>() { 1, 2 };
var result = new StringBuilder();
foreach (var id in ids)
{
var resClass = fluent.GetById(id).IncludeRecords().IncludeMetaData().Get();
result.Append($"Id : {id}, Records: {resClass.Records.Count}, MetaData: {resClass.MetaData.Count}{Environment.NewLine}");
}
return result.ToString();
}
}
Current incorrect result
/*Id : 1, Records: 0, MetaData: 3
Id : 2, Records: 0, MetaData: 3*/
Expected Result
/*Id : 1, Records: 3, MetaData: 0
Id : 2, Records: 0, MetaData: 3*/
The easiest way would be to split out each setup:
var mock = new Mock<IFluent>();
var mock1 = new Mock<IFluent>();
var mock2 = new Mock<IFluent>();
mock.Setup(x => x.GetById(1)).Returns(mock1.Object);
mock1.Setup(x => x.IncludeRecords()).Returns(mock1.Object);
mock1.Setup(x => x.IncludeMetaData()).Returns(mock1.Object);
mock1.Setup(x => x.Get()).Returns(c1);
mock.Setup(x => x.GetById(2)).Returns(mock2.Object);
mock2.Setup(x => x.IncludeRecords()).Returns(mock2.Object);
mock2.Setup(x => x.IncludeMetaData()).Returns(mock2.Object);
mock2.Setup(x => x.Get()).Returns(c2);
var result = new ComputeClass().ComputeStuff(mock.Object);
You could create an extension/utility to handle this all for you if you wanted something a bit more complex, take a look at this blog post: https://www.codemunki.es/2014/11/20/mocking-a-fluent-interface-automatically-in-moq/
Just an addition to the already existing answer. For mocking fluent API there is one usefull option within the moq, it is SetReturnsDefault, it could save some mocking especially if you have huge fluent API, e.g.
var mock = new Mock<IFluent>();
var mock1 = new Mock<IFluent>();
var mock2 = new Mock<IFluent>();
mock.Setup(x => x.GetById(1)).Returns(mock1.Object);
mock1.SetReturnsDefault(mock1.Object);
mock1.Setup(x => x.Get()).Returns(a);
mock.Setup(x => x.GetById(2)).Returns(mock2.Object);
mock2.SetReturnsDefault(mock2.Object);
mock2.Setup(x => x.Get()).Returns(b);
var aa = mock.Object.IncludeMetaData().GetById(1).IncludeMetaData().Get();
var bb = mock.Object.IncludeMetaData.GetById(2).IncludeMetaData.Get();
With this approach you actually have to mock only method which differ but not the all methods from fluent API.
Related
I'm trying to write unit test using xUnit for EntityService class which is using Dapper to get data from Sqllite database. In my unit test it always returns actual values as List<Entity> [] and test fails. I'm not understanding what I am missing here.
Test Class
public class EntityServiceTests
{
private readonly IEntityService _sut;
private readonly Mock<IEntityService> _entityServiceMock;
public EntityServiceTests()
{
_entityServiceMock = new Mock<IEntityService>();
var dapperMock = new Mock<IDapperWrapper>();
_sut = new EntityService(dapperMock.Object);
}
[Fact]
public void GetEntities_ShouldReturnEntities()
{
//Arrange
var expectedEntities = new List<Entity>
{
new()
{
Id = 1,
Name = "Test",
X = 12,
Y = 14.5,
CoordId = 1
},
new()
{
Id = 2,
Name = "Test2",
X = 16,
Y = 18.5,
CoordId = 2
}
};
var query = #"SELECT ent.*, crd.x, crd.y, crd.id as CoordId
FROM entities ent
INNER JOIN coords crd ON crd.entityId = ent.Id";
_entityServiceMock.Setup(x => x.GetEntities(0)).Returns(expectedEntities);
//Act
var entities = _sut.GetEntities(0).ToList();
//Assert
Assert.Equal(expectedEntities, entities);
}
}
Service Class
public class EntityService : IEntityService
{
private readonly IDapperWrapper _dapperWrapper;
public EntityService(IDapperWrapper dapperWrapper)
{
_dapperWrapper = dapperWrapper;
}
public IEnumerable<Entity> GetEntities(int entityId)
{
var query = #"SELECT ent.*, crd.x, crd.y, crd.id as CoordId
FROM entities ent
INNER JOIN coords crd ON crd.entityId = ent.Id ";
if (entityId > 0)
{
query += " WHERE ent.id = #id";
var entities = _dapperWrapper.Query<Entity>(query, new { id = entityId });
return entities;
}
else
{
var entities = _dapperWrapper.Query<Entity>(query);
return entities;
}
}
}
Dapper Wrapper Class
public class DapperWrapper : IDapperWrapper
{
private IDbConnection Connection { get; }
public DapperWrapper()
{
Connection = new SQLiteConnection(GetConnectionString("ConnectionString"));
}
private string GetConnectionString(string name)
{
return ConfigurationManager.ConnectionStrings[name].ConnectionString;
}
public IEnumerable<T> Query<T>(string query)
{
return Connection.Query<T>(query);
}
public IEnumerable<T> Query<T>(string query, object param)
{
return Connection.Query<T>(query, param);
}
public T QuerySingle<T>(string query, object param)
{
return Connection.QuerySingle<T>(query, param);
}
}
Normally the project is working fine. but in Test it fails. I think i'm missing something very basic but crucial.
UPDATE: I'm using this code now but still getting failed result
[Fact]
public void GetEntities_Should_Return_All_Entities_If_0_Is_Provided_In_Param()
{
//Arrange
var expectedEntities = new List<Entity>
{
new()
{
Id = 1,
Name = "Test",
X = 12,
Y = 14.5,
CoordId = 1
},
new()
{
Id = 2,
Name = "Test2",
X = 16,
Y = 18.5,
CoordId = 2
}
};
var query = #"SELECT ent.*, crd.x, crd.y, crd.id as CoordId
FROM entities ent
INNER JOIN coords crd ON crd.entityId = ent.Id ";
var dapperMock = new Mock<IDapperWrapper>();
dapperMock.Setup(x => x.Query<Entity>(query)).Returns(expectedEntities);
var sut = new EntityService(dapperMock.Object);
//Act
var entities = sut.GetEntities(0);
//Assert
Assert.Equal(expectedEntities, entities);
}
I think i'm missing something very basic but crucial.
Indeed 🙂 mocking is intended to be used to mock away the dependencies from a unit to test (sut). In your case your unit to test is the EntityService and the dependency to mock away is IDapperWrapper.
But instead of only mocking the dependency, you're mocking the SUT as well with _entityServiceMock.
So you COULD try to do it like this within your test:
public class EntityServiceTests
{
[Fact]
public void GetEntities_ShouldReturnEntities()
{
//Arrange
var expectedEntities = new List<Entity>
{
new()
{
Id = 1,
Name = "Test",
X = 12,
Y = 14.5,
CoordId = 1
}
};
var query = #"SELECT ent.*, crd.x, crd.y, crd.id as CoordId
FROM entities ent
INNER JOIN coords crd ON crd.entityId = ent.Id WHERE ent.id = #id";
var dapperMock = new Mock<IDapperWrapper>();
dapperMock.Setup(x => x.Query<Entity>(query, 1)).Returns(expectedEntities.First());
var sut = new EntityService(dapperMock.Object);
//Act
var entities = sut.GetEntities(1).ToList();
//Assert
Assert.Equal(expectedEntities, entities);
}
}
But I highly discourage you from doing so because you'll end up mocking all the Dapper stuff.
Instead you better use an in-memory database (like SQLite), use a real Dapper instance. This way your tests will become much more comprehensive, shorter and business-facing. This blog post should give you a good starting point.
I try to Setup a mock for Update function,
public class JelentkezokService : IJelentkezokService
{
IJelentkezokRepository JelentkezokRepository { get; set; }
public Jelentkezok Update(Jelentkezok jelentkezo)
{
if (JelentkezokRepository.GetAll().Any(x => x.Id == jelentkezo.Id))
{
return JelentkezokRepository.Update(jelentkezo);
}
//The ID is not exist
else throw new Exception($"A megadott jelentkező ID nem létezik: {jelentkezo.Id}");
}
}
testing whether the function was called but it goes for the exception in the Service. Any idea?
[TestFixture]
public class JelentkezokBLTests
{
Mock<IJelentkezokRepository> JelentkezokRepositoryMock;
[Test]
public void JelentkezokUpdateMeghivva()
{
//Arrange
JelentkezokRepositoryMock = new Mock<IJelentkezokRepository>();
var input = new DA.Jelentkezok()
{
Id = 13,
Nev = "Kis Béla",
Varos = "Győr",
Utca = "Kodály Zoltán u. 15.",
SzuletesiDatum = new DateTime(1982, 11, 19),
Iranyitoszam = 9030,
Ferfi = true,
};
var mockedResult = new DA.Jelentkezok()
{
Id = 13,
Nev = "Kis Anita",
Varos = "Győr",
Utca = "Kodály Zoltán u. 15.",
SzuletesiDatum = new DateTime(1982, 11, 19),
Iranyitoszam = 9030,
Ferfi = false,
};
JelentkezokRepositoryMock.Setup(x => x.Update(input)).Returns(mockedResult);
JelentkezokService service = new JelentkezokService(JelentkezokRepositoryMock.Object);
//Act
var updateJelentkezo = service.Update(input);
//Assert
//Assert.That(input, Is.Not.Null);
JelentkezokRepositoryMock.Verify(v => v.Update(input), Times.AtLeastOnce);
}
I have the error
Message: System.Exception : A megadott jelentkező ID nem létezik: 13 //The ID is not exist.
Looks like JelentkezokRepository.GetAll() is not behaving as expected.
Assuming it returns a collection
IEnumerable<Jelentkezok> GetAll();
That may need to be setup as well.
//...
var item = new DA.Jelentkezok() {
Id = 13,
};
var all = new [] { item };
JelentkezokRepositoryMock.Setup(x => x.GetAll()).Returns(all);
//...
In order to allow the if condition to flow as expected when the test is exercised.
I use Automapper version 4.2.0 and I all Action Methods I have setting Like this :
var attributeGroups = _attributeGroupService.AttributeGroupDropdown();
var mapconfiguration = new MapperConfiguration(cfg => cfg.CreateMap<AttributeGroup, AttributeGroupViewModel>());
var mapper = mapconfiguration.CreateMapper();
var result = mapper.Map(attributeGroups, new List<AttributeGroupViewModel>());
I dont repeat this codes in all actions , I want create a generic method and just pass data to it and map it ,to do this , I create a Method like this ?
public N mapping<T,K,M,N>(T resource, K destination,M model,N newModel)
{
var mapconfiguration = new MapperConfiguration(cfg => cfg.CreateMap<T, K>());
var mapper = mapconfiguration.CreateMapper();
var result = mapper.Map<M,N>(model, newModel);
return result;
}
and call it like this :
var ResultTest=mapping<AttributeGroup,AttributeGroupViewModel,attributeGroups,new List<AttributeGroupViewModel>()>();
but it doesnt complie .
how can I do it?
Short answer: you need to provide types in the generic parameter list and variables in the argument list of your function call. Also, you don't need the T resource, K destination arguments at all, since they are unused.
There is another problem with your approach, since using it is not really convenient. So I suggest that you provide two specialized methods with reduced complexity.
See the below complete example. It contains the method mapAnything<...>, which is a working equivalent to your mapping<...> method. The methods mapObject<...> and mapCollection<...> are the specialized methods I was talking about.
class TestResource
{
public int Testnumber { get; set; }
public string Testtext { get; set; }
}
class TestDestination
{
public string Testtext { get; set; }
}
class Program
{
// equivalent to what you tried to do - needs explicit generic parameters on call
static N mapAnything<T, K, M, N>(M model, N newModel)
{
var mapconfiguration = new MapperConfiguration(cfg => cfg.CreateMap<T, K>());
var mapper = mapconfiguration.CreateMapper();
var result = mapper.Map<M, N>(model, newModel);
return result;
}
// variant for object mapping, where generics can be implicitely inferred
static N mapObject<M, N>(M model, N newModel)
{
var mapconfiguration = new MapperConfiguration(cfg => cfg.CreateMap<M, N>());
var mapper = mapconfiguration.CreateMapper();
var result = mapper.Map<M, N>(model, newModel);
return result;
}
// variant for lists, where generics can be implicitely inferred
static ICollection<N> mapCollection<M, N>(IEnumerable<M> model, ICollection<N> newModel)
{
var mapconfiguration = new MapperConfiguration(cfg => cfg.CreateMap<M, N>());
var mapper = mapconfiguration.CreateMapper();
var result = mapper.Map<IEnumerable<M>, ICollection<N>>(model, newModel);
return result;
}
static void Main(string[] args)
{
var res1 = new TestResource() { Testnumber = 1, Testtext = "a" };
var res2 = new List<TestResource>();
for (int i = 0; i < 10; i++)
{
res2.Add(new TestResource() { Testnumber = i, Testtext = "test: " + i });
}
var mapped1 = mapObject(res1, new TestDestination());
var mapped2 = mapCollection(res2, new HashSet<TestDestination>());
var mapped3 = mapAnything<TestResource, TestDestination, TestResource, TestDestination>(res1, new TestDestination());
var mapped4 = mapAnything<TestResource, TestDestination, IEnumerable<TestResource>, List<TestDestination>>(res2, new List<TestDestination>());
}
}
I was trying to unit test my repository. I need to mock the Where Clause with some values.
I have tried the following
var parentClass = new ParentClass {id = 1};
var subClass = new SubClass
{
id=2,
ParentClassId = parentClass.id,
ParentClass = parentClass
}
var subSubClass = new SubSubClass
{
id =3,
SubClassId = subClass.id,
SubClass = subClass
}
var dbContext = MockRepository.GenerateMock<IDbContext>();
var subClassContext = MockRepository.GenerateMock<IDbSet<SubClass>>();
var subSubClassContext = MockRepository.GenerateMock<IDbSet<SubSubClass>>();
subClassContext.Stub(x => x.GetEnumerator())
.Return(null)
.WhenCalled(c => c.ReturnValue = new List<SubClass> { subClass }.GetEnumerator());
subSubClassContext.Stub(x => x.GetEnumerator())
.Return(null)
.WhenCalled(c => c.ReturnValue = new List<SubSubClass> { subSubClass }.GetEnumerator());
I am testing the following code
var existingSubSubClasses = context.SubSubClass.Where(cba => cba.SubClass.ParentClassId == parentClassId).ToList();
I am getting ArgumentNullReferenceException
What am I doing wrong?
You should also stub context.SubSubClass property -- seems like it returns null by default.
I need to test logic that executes a function, after which it changes a property on the parameter and then executes the same function with the updated parameter.
To help illustrate this, here is some sample code:
Interface:
public interface IWorker
{
MyObjectB DoWork(MyObject myObject);
}
MyObjectB:
public class MyObjectB
{
public string Message { get; set; }
}
Implementation:
public MyObjectB DoWork(IWorker worker, MyObject myObject)
{
worker.DoWork(myObject);
myObject.Name = "PersonB";
worker.DoWork(myObject);
return new MyObjectB() { Message = "Done" };
}
Test:
public void RhinoMocksSampleTest()
{
var workerStub = MockRepository.GenerateStub<IWorker>();
workerStub.Stub(n => n.DoWork(Arg<MyObject>.Is.Anything));
var myObj = new MyObject { Id = 1, Name = "PersonA" };
var p = new Program();
p.DoWork(workerStub, myObj);
workerStub.AssertWasCalled(d => d.DoWork(Arg<MyObject>.Matches(r => r.Name == "PersonA")));
workerStub.AssertWasCalled(d => d.DoWork(Arg<MyObject>.Matches(r => r.Name == "PersonB")));
}
The first AssertWasCalled fails because the value is ‘PersonB’.
Is there a function/call I can use to test the state of the object for the first call?
Here's how I would do what you're trying to do:
public void RhinoMocksSampleTest()
{
var workerMock = MockRepository.GenerateMock<IWorker>();
workerMock.Expect(d => d.DoWork(Arg<MyObject>.Matches(r => r.Name == "PersonA")));
workerMock.Expect(d => d.DoWork(Arg<MyObject>.Matches(r => r.Name == "PersonB")));
var myObj = new MyObject { Id = 1, Name = "PersonA" };
var p = new Program();
p.DoWork(workerMock , myObj);
workerMock.VerifyAllExpectations();
}
In addition to nice answer what aprescott has provided I can show another one approach which could be useful in some situations:
The idea is to manually store values which you are interesting in into some collection. Then you will be able to assert that collection contains required sequense.
public void MyTest()
{
// that is list which will contain passed names
var actualNames = new List<string>();
// stub only saves passed Name property into list
var workerStub = MockRepository.GenerateStub<IWorker>();
workerStub
.Stub(w => w.DoWork(Arg<MyObject>.Is.Anything))
.Do((Action<MyObject>)(mo => actualNames.Add(mo.Name)));
var myObject = new MyObject { Name = "PersonA" };
var target = new MyWorker();
target.DoWork(workerStub, myObject);
// here we do assert that names list contains what is required
Assert.That(actualNames, Is.EqualTo(new[] { "PersonA", "PersonB" }));
}
PS. Yeah, it works for case when you need check that calls order is correct :)