I have a class, a service, and two interfaces:
public class MyBasicObject
{
public MyBasicObject() { }
public int Id { get; set; }
public string Name { get; set; }
}
public interface ICacheProvider
{
T Get<T>(string key, Func<T> fetcher) where T:class;
}
public interface IMyBasicObjectRepository
{
MyBasicObject GetByName(string name);
}
public class MyBasicObjectService
{
public MyBasicObjectService(ICacheProvider cacheProvider,
IMyBasicObjectRepository repository)
{
CacheProvider = cacheProvider;
MyBasicObjectRepository = repository;
}
public ICacheProvider CacheProvider { get; set; }
public IMyBasicObjectRepository MyBasicObjectRepository { get; set; }
public MyBasicObject GetByName(string name)
{
return CacheProvider.Get<MyBasicObject>(name, () =>
MyBasicObjectRepository.GetByName(name));
}
}
Using RhinoMocks, I'd like to be able to verify that when MyBasicObjectService.GetByName("AnUniqueName") gets executed, so does CacheProvider.Get("AnUniqueName", () => MyBasicObjectRepository.GetByName("AnUniqueName")). I have a fixture set up like so:
[TestFixture]
public class MyBasicObjectServiceFixture
{
[Test]
public void GetByNameShouldCallCacheProviderFunction()
{
// Arrange
MockRepository mock = new MockRepository();
IMyBasicObjectRepository repo = mock.DynamicMock<IMyBasicObjectRepository>();
ICacheProvider cacheProvider = mock.DynamicMock<ICacheProvider>();
MyBasicObjectService service = new MyBasicObjectService(cacheProvider, repo);
cacheProvider.Expect(p => p.Get<MyBasicObject>("AnUniqueName", () => repo.GetByName("AnUniqueName")));
mock.ReplayAll();
// Act
var result = service.GetByName("AnUniqueName");
// Assert
mock.VerifyAll();
}
}
I would expect this test to pass, but when run, the assertion fails, notifying me that the function laid out in cacheProvider.Expect is not being called. Am I missing something reg. mocking out and testing methods that take parameters of Func<>?
Edit:
So if I do:
cacheProvider.Expect(p => p.Get<MyBasicObject>("AnUniqueName", () => repo.GetByName("AnUniqueName"))).IgnoreArguments();
(that is to say, add the IgnoreArguments() method onto the end of the expect call)
...the test passes just fine. I'm assuming, then, it's a problem with the argument passed in. Is there something I'm doing wrong in the expect where the cache provider method is getting called but it chokes on the anonymous method getting passed in?
The problem is that the two anonymous methods (the one in the Expect and the one which is created in GetByName are two different objects and therefor are not equal. You can fix that by partially matching the arguments like this:
cacheProvider.Expect(p => p.Get<MyBasicObject>(Arg<string>.Is.Equal("AnUniqueName"), Arg <Func<MyBasicObject>>.Is.NotNull));
What I ended up doing for the test was:
[TestFixture]
public class MyBasicObjectServiceFixture
{
[Test]
public void GetByNameShouldCallCacheProviderFunction()
{
// Arrange
MockRepository mock = new MockRepository();
IMyBasicObjectRepository repo = mock.DynamicMock<IMyBasicObjectRepository>();
ICacheProvider cacheProvider = mock.DynamicMock<ICacheProvider>();
MyBasicObjectService service = new MyBasicObjectService(cacheProvider, repo);
cacheProvider.Expect(p => p.Get<MyBasicObject>(Arg<string>.Is.Equal("AnUniqueName"), Arg<Func<MyBasicObject>>.Is.NotNull))
.WhenCalled(call =>
{
var repoCall = (Func<MyBasicObject>)call.Arguments[1];
repoCall.Invoke();
});
repo.Expect(c => c.GetByName("AnUniqueName"));
mock.ReplayAll();
// Act
var result = service.GetByName("AnUniqueName");
// Assert
mock.VerifyAll();
}
}
This works specifically for my use case (invoking a database retrieval in case of a cache miss, and making sure the service uses the correct repository call at that time), but is sort of a not-so-great work-around if you're not planning on invoking the anonymous function right away. I'm sure there are other alternatives with .WhenCalled, but for right now, this is working for me.
Related
I'm pretty new in .NET and I have to mock GetCustomerDetailsAsync endpoint using a local json file in order to get the file results and create a way to enable and disable the mocking mechanism. Here is the handler where I have to implement the logic
public class GetCustomerDetailsQueryHandler : IRequestHandler<GetCustomerDetailsQuery, CustomerInsertionModel>
{
private readonly ICustomerApiClient _customerApiClient;
private readonly IAccountApiClientGraphQl _accountApiClientGraphQl;
private readonly IMapper _mapper;
private readonly IMediator _mediator;
private readonly IOptions<CommonFeaturesOptions> _commonFeaturesOptions;
public GetCustomerDetailsQueryHandler(ICustomerApiClient customerApiClient,
IAccountApiClientGraphQl accountApiClientGraphQl,
IMediator mediator,
IMapper mapper,
IOptions<CommonFeaturesOptions> commonFeaturesOptions)
{
_customerApiClient = customerApiClient ?? throw new ArgumentNullException(nameof(customerApiClient));
_accountApiClientGraphQl = accountApiClientGraphQl ?? throw new ArgumentNullException(nameof(accountApiClientGraphQl));
_mediator = mediator;
_mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
_commonFeaturesOptions = commonFeaturesOptions ?? throw new ArgumentNullException(nameof(commonFeaturesOptions));
}
public async Task<CustomerInsertionModel> Handle(GetCustomerDetailsQuery request, CancellationToken cancellationToken)
{
//if(!EnablePostfixations){
//var customerApiResponse = (await _customerApiClient.GetCustomerDetailsAsync(_mapper.Map<GetCustomerDetailsRequest>(request)))
// .CustomerDetails.FirstOrDefault();
//}
//else
//{
//var response = await _customerApiClient.GetCustomerDetailsAsync(
// _mapper.Map<GetCustomerDetailsRequest>((request, _commonFeaturesOptions.Value)));
var customerApiResponse = (await _customerApiClient.GetCustomerDetailsAsync(_mapper.Map<GetCustomerDetailsRequest>(request)))
.CustomerDetails.FirstOrDefault();
if (customerApiResponse is null)
{
return new CustomerInsertionModel((false, string.Empty))
.MarkCustomerAsNotFound();
}
var customer = new CustomerInsertionModel(customerApiResponse.Cif,
customerApiResponse.CnpCui,
customerApiResponse.Category,
customerApiResponse.Insolvency,
request.AddInsolvency,
request.CloseCustomerCategories.ToList());
return customer
}
}
commented lines are just for guidence (what to do, inject an IOptions with a boolean that decide when to enable and disable the mocking mechanism )
plus I wanna know where should I have to deserialize the file(in handler or outside of it?)
public class DeserializeFromFileAsync
{
public class PostfixationsFile
{
public string Customer_no { get; set; }
public string First_name { get; set; }
public string Last_name { get; set; }
public string Customer_type { get; set; }
public string Adress_line { get; set; }
public int Cnp { get; set; }
public string Customer_category { get; set; }
public int Open_branch { get; set; }
public string Branch_name { get; set; }
public string Insolventa { get; set; }
}
public class Program
{
public static async Task Main()
{
string fileName = #"FullPath";
using FileStream openStream = File.OpenRead(fileName);
PostfixationsFile weatherForecast = await JsonSerializer.DeserializeAsync<PostfixationsFile>(openStream);
}
}
}
and this is the json file.
[
{ "customer_no": "03242524",
"first_name": "Prenume",
"last_name": "Nume",
"customer_type": "PF",'
"adress_line": " Str. FN Nr. Bl. Sc. Et. Ap. Sect. Loc. Jud. ",
"cnp": "1970907336523",
"customer_category": "PF_ONLINE",
"open_branch": "213",
"branch_name": "SUCURSALA DEJ",
"insolventa": "NU"
},
{ "customer_no": "03242524",
"first_name": "Prenume",
"last_name": "Nume",
"customer_type": "PF",'
"adress_line": " Str. FN Nr. Bl. Sc. Et. Ap. Sect. Loc. Jud. ",
"cnp": "1970907336523_J77",
"customer_category": "PF_ONLINE",
"open_branch": "213",
"branch_name": "SUCURSALA DEJ",
"insolventa": "NU"
}
]
Sorry for this messy message but is first time when I ask something here.
I wasn't able to build your code as it has a lot of dependencies which I'd need to make all sorts of assumptions about - you may want to read about creating a minimal, reproducible example.
However, I should be able to help you to understand how to use mocks. The first thing to know about mocks is that they should only be used in unit tests, not in your production code. So you wouldn't want to pass a flag into your actual handler to tell it whether or not to run in "mock" mode. Instead, you can create an instance of a mock in your unit test and then inject the mock into the code you're testing, so that your unit test can concentrate on the behaviour of the code you're testing, rather than the behaviour of any external code / web service / database etc that it is dependent on.
Imagine this is the class you want to test (equivalent of your GetCustomerDetailsQueryHandler).
public class MyHandler
{
private readonly IThingToMock thingToMock;
public MyHandler(IThingToMock thingToMock)
{
this.thingToMock = thingToMock;
}
public string MethodToTest(int id)
{
var request = new RequestModel { Id = id };
var response = this.thingToMock.GetInformation(request);
return response.Foo;
}
public async Task<string> MethodToTestAsync(int id)
{
var request = new RequestModel { Id = id };
var response = await this.thingToMock.GetInformationAsync(request).ConfigureAwait(false);
return response.Foo;
}
}
This is dependent on IThingToMock (equivalent of your ICustomerApiClient), which looks like this:
public interface IThingToMock
{
ResponseModel GetInformation(RequestModel request);
Task<ResponseModel> GetInformationAsync(RequestModel request);
}
And IThingToMock's request and response models look like this (I've deliberately kept them really simple):
public class RequestModel
{
public int Id { get; set; }
}
public class ResponseModel
{
public string Foo { get; set; }
}
Before you can start mocking, you need to add a unit test project to your solution (in Visual Studio's new project wizard, choose the template for a xUnit, nUnit or MSTest unit test project - which one you use is a matter of personal preference, I'm using xUnit for this answer).
Next, add a mocking NuGet package to your test project and add the appropriate using directive to your unit tests, e.g. using Moq;. I'm using Moq here, but again, other mocking packages are available, and it's up to you which one you want to use.
Now you can write a unit test, like this:
[Fact]
public void MethodToTest_AnyRequest_ReturnsExpectedResponse()
{
// Arrange
var mockThing = new Mock<IThingToMock>();
var expectedFoo = "Bar";
mockThing.Setup(m => m.GetInformation(It.IsAny<RequestModel>()))
.Returns(new ResponseModel { Foo = expectedFoo });
var handler = new MyHandler(mockThing.Object);
// Act
var actualFoo = handler.MethodToTest(1);
// Assert
Assert.Equal(expectedFoo, actualFoo);
}
Let's break this down. First, we create an instance of Mock<IThingToMock>. This has an Object property, which is an implementation of IThingToMock with all its methods and properties, except that by default the methods do nothing and any members with a return value return the default value for their return type (usually null).
Next, we use the Setup method to make our mock behave in the way we want. In this example, we're saying that its GetInformation method should always return a particular ResponseModel regardless of the properties of the RequestModel which were passed to it. I'm telling it to return a hard-coded value here, but you could tell the mock to return the data deserialized from your JSON file instead.
And then at the end of the Arrange step, we're injecting the mocked IThingToMock into the constructor of the MyHandler class, which is the class we want to test the behaviour of.
To control the behaviour of an asynchronous method, set up the mock using the ReturnsAsync method instead of Returns, for example:
[Fact]
public async Task MethodToTestAsync_AnyRequest_ReturnsExpectedResponse()
{
// Arrange
var mockThing = new Mock<IThingToMock>();
var expectedFoo = "Bar";
mockThing.Setup(m => m.GetInformationAsync(It.IsAny<RequestModel>()))
.ReturnsAsync(new ResponseModel { Foo = expectedFoo });
var handler = new MyHandler(mockThing.Object);
// Act
var actualFoo = await handler.MethodToTestAsync(1);
// Assert
Assert.Equal(expectedFoo, actualFoo);
}
Hopefully these examples give you sufficient insight into how mocks are used in unit tests to be able to apply the principles to your own situation. You may also want to read How YOU can Learn Mock testing in .NET Core and C# with Moq, which provides more examples of how to use Moq, this time with nUnit rather than xUnit, as well as some good practice around unit testing generally. And of course, be sure to consult the documentation for whichever mocking package you're using.
Happy mocking!
My WEB API project is using a Generic Repository that implements an interface like this:
public interface IGenericEFRepository<TEntity> where TEntity : class
{
Task<IEnumerable<TEntity>> Get();
Task<TEntity> Get(int id);
}
public class GenericEFRepository<TEntity> : IGenericEFRepository<TEntity>
where TEntity : class
{
private SqlDbContext _db;
public GenericEFRepository(SqlDbContext db)
{
_db = db;
}
public async Task<IEnumerable<TEntity>> Get()
{
return await Task.FromResult(_db.Set<TEntity>());
}
public async Task<TEntity> Get(int id)
{
var entity = await Task.FromResult(_db.Set<TEntity>().Find(new object[] { id }));
if (entity != null && includeRelatedEntities)
{
//Some Code
}
return entity;
}
}
Well now I want to test this service. for this I have used the following code:
public class CustomerControllerTest
{
CustomerController _controller;
ICustomerProvider _provider;
ICustomerInquiryMockRepository _repo;
public CustomerControllerTest()
{
_repo = new CustomerInquiryMockRepository();
_provider = new CustomerProvider(_repo);
_controller = new CustomerController(_provider);
}
[Fact]
public async Task Get_WhenCalled_ReturnsOkResult()
{
// Act
var okResult = await _controller.Get();
// Assert
Assert.IsType<OkObjectResult>(okResult);
}
[Fact]
public async Task GetById_UnknownCustomerIdPassed_ReturnsNotFoundResult()
{
// Act
var notFoundResult = await _controller.Get(4);
// Assert
Assert.IsType<NotFoundResult>(notFoundResult);
}
}
Which my tests are working fine by creating a fake non-generic service manually with mock data (In-Memory) like below, instead of using my real generic interface and it's implementation that uses my database as data-source:
public interface ICustomerInquiryMockRepository
{
Task<IEnumerable<CustomerDTO>> GetCustomers();
Task<CustomerDTO> GetCustomer(int customerId);
}
And it's implementation:
public class CustomerInquiryMockRepository : ICustomerInquiryMockRepository
{
public async Task<IEnumerable<CustomerDTO>> GetCustomers()
{
return await Task.FromResult(MockData.Current.Customers);
}
public async Task<CustomerDTO> GetCustomer(int CustomerId)
{
var Customer = await Task.FromResult(MockData.Current.Customers.FirstOrDefault(p => p.CustomerID.Equals(CustomerId)));
if (includeTransactions && Customer != null)
{
Customer.Transactions = MockData.Current.Transactions.Where(b => b.CustomerId.Equals(CustomerId)).ToList();
}
return Customer;
}
}
And the MockData.Current.Customers is just a simple fake (In-Memory) List of Customers. Long story short, the above tests are working fine, however I am feeling I have repeated my self a lot and so I have decided to use Moq library instead of creating fake service manually. For this purpose I have used Moq like this:
public class CustomerControllerTest
{
CustomerController _controller;
ICustomerProvider _provider;
//ICustomerInquiryMockRepository _repo;
Mock<ICustomerInquiryMockRepository> mockUserRepo;
public CustomerControllerTest()
{
mockUserRepo = new Mock<ICustomerInquiryMockRepository>();
//_repo = new CustomerInquiryMockRepository();
_provider = new CustomerProvider(mockUserRepo.Object);
_controller = new CustomerController(_provider);
}
[Fact]
public async Task Get_WhenCalled_ReturnsOkResult()
{
mockUserRepo.Setup(m => m.GetCustomers())
.Returns(Task.FromResult(MockData.Current.Customers.AsEnumerable()));
// Act
var okResult = await _controller.Get();
// Assert
Assert.IsType<OkObjectResult>(okResult);
}
[Fact]
public async Task GetById_UnknownCustomerIdPassed_ReturnsNotFoundResult()
{
//Arrange
I don't know how can I use Moq here and in the other parts of my tests
// Act
var notFoundResult = await _controller.Get(4);
// Assert
Assert.IsType<NotFoundResult>(notFoundResult);
}
Now my question is the Mock is working fine when I use it for Mocking the GetCustomers method because I simply paste the code from GetCustomers method in the CustomerInquiryMockRepository in the Returns method of the Mock object. However I don't really have any idea how can I use Mock for my other methods inside this Repository. Should I replace anything that I have in the Return method?
You can mock out your repository like so:
var mockUserRepo = new Mock<ICustomerInquiryMockRepository>();
mockUserRepo.Setup(x => x.GetCustomers())
.Returns(Task.FromResult(MockData.Current.Customers.AsEnumerable());
mockUserRepo.Setup(x => x.GetCustomer(It.IsAny<int>()))
.Returns(res => Task.FromResult(MockData.Current.Customers.ElementAt(res));
If you want to mock out specific values for GetCustomer, you can do:
mockUserRepo.Setup(x => x.GetCustomer(It.Is<int>(y => y == 4)))
.Returns(res => Task.FromResult(/* error value here */));
I think the key here is to use It.Is or It.IsAny based on how you want to mock out the object. Generally, you also want to mock out interfaces that are used in production code, instead of having production code depend on something with Mock or Test in the name. I would recommend against taking a production code dependency on something named ICustomerInquiryMockRepository, if that is indeed what you're doing and not just part of the MCVE you've provided.
Tests usually use mocking to test the workflow of an application at a high level, so you would usually want to mock out your services level, call a controller, and verify that the services were called as expected. For example:
// Production class sample
class ProductionController
{
public ProductionController(IService1 service1, IService2 service2) { }
public void ControllerMethod()
{
var service1Result = service1.Method();
service2.Method(service1Result);
}
}
// Test sample
// arrange
var expectedResult = new Service1Result();
var service1 = Mock.Of<IService1>(x => x.Method() == expectedResult);
var service2 = Mock.Of<IService2>(x => x.Method(It.Is<Service1Result>(y => y == expectedResult)));
var controller = new ProductionController(service1, service2);
// act
controller.ControllerMethod();
// assert
Mock.Get(service1).Verify(x => x.Method(), Times.Once);
Mock.Get(service2).Verify(x => x.Method(expectedResult), Times.Once);
As you can see from the example, you aren't checking the business logic of either of the services, you're just validating that the methods were called with the expected data. The test is built around verification of methods being called, not any particular branching logic.
Also, unrelated to your question, Moq also has a cool syntax you can use for simple mock setups:
var repo = Mock.Of<ICustomerInquiryMockRepository>(x =>
x.GetCustomers() == Task.FromResult(MockData.Current.Customers.AsEnumerable()));
You can use Mock.Get(repo) if you need to do additional setup on the repository. It's definitely worth checking out, I find it much nicer to read.
I'm having a difficult time trying to understand how to appropriately return mocked data from a simulated database call in a unit test.
Here's an example method I want to unit test (GetBuildings):
public class BuildingService : IBuildingService {
public IQueryable<Building> GetBuildings(int propertyId)
{
IQueryable<Building> buildings;
// Execution path for potential exception thrown
// if (...) throw new SpecialException();
// Another execution path...
// if (...) ...
using (var context = DataContext.Instance())
{
var Params = new List<SqlParameter>
{
new SqlParameter("#PropertyId", propertyId)
};
// I need to return mocked data here...
buildings = context
.ExecuteQuery<Building>(System.Data.CommandType.StoredProcedure, "dbo.Building_List", Params.ToArray<object>())
.AsQueryable();
}
return buildings;
}
}
So GetBuildings calls a stored procedure.
So I need to mock the DataContext, that of which I can override and set a testable instance. So what happens here is, in the above example DataContext.Instance() does return the mocked object.
[TestFixture]
public class BuildingServiceTests
{
private Mock<IDataContext> _mockDataContext;
[SetUp]
public void Setup() {
_mockDataContext = new Mock<IDataContext>();
}
[TearDown]
public void TearDown() {
...
}
[Test]
public void SomeTestName() {
_mockDataContext.Setup(r =>
r.ExecuteQuery<Building>(CommandType.StoredProcedure, "someSproc"))
.Returns(new List<Building>() { new Building() { BuildingId = 1, Title = "1" }}.AsQueryable());
DataContext.SetTestableInstance(_mockDataContext.Object);
var builings = BuildingService.GetBuildings(1, 1);
// Assert...
}
Please ignore some of the parameters, like propertyId. I've stripped those out and simplified this all. I simply can't get the ExecuteQuery method to return any data.
All other simple peta-poco type methods I can mock without issue (i.e. Get, Insert, Delete).
Update
DataContext.Instance returns the active instance of the DataContext class, if exists, and if not exists, returns a new one. So the method of test under question returns the mocked instance.
Do not mock DataContext. Because mocking DataContext will produce tests tightly coupled to the implementation details of DataContext. And you will be forced to change tests for every change in the code even behavior will remain same.
Instead introduce a "DataService" interface and mock it in the tests for BuildingService.
public interface IDataService
{
IEnumerable<Building> GetBuildings(int propertyId)
}
Then, you can tests implementation of IDataService agains real database as part of integration tests or tests it agains database in memory.
If you can test with "InMemory" database (EF Core or Sqlite) - then even better -> write tests for BuildingService against actual implementation of DataContext.
In tests you should mock only external resources (web service, file system or database) or only resources which makes tests slow.
Not mocking other dependencies will save you time and give freedom while you refactoring your codebase.
After update:
Based on the updated question, where BuildingService have some execution path - you can still testing BuildingService and abstract data related logic to the IDataService.
For example below is BuildingService class
public class BuildingService
{
private readonly IDataService _dataService;
public BuildingService(IDataService dataService)
{
_dataService = dataService;
}
public IEnumerable<Building> GetBuildings(int propertyId)
{
if (propertyId < 0)
{
throw new ArgumentException("Negative id not allowed");
}
if (propertyId == 0)
{
return Enumerable.Empty<Building>();
}
return _myDataService.GetBuildingsOfProperty(int propertyId);
}
}
In tests you will create a mock for IDataService and pass it to the constructor of BuildingService
var fakeDataService = new Mock<IDataContext>();
var serviceUnderTest = new BuildingService(fakeDataService);
Then you will have tests for:
"Should throw exception when property Id is negative"
"Should return empty collection when property Id equals zero"
"Should return collection of expected buildings when valid property Id is given"
For last test case you will mock IDataService to return expected building only when correct propertyId is given to _dataService.GetBuildingsOfProperty method
In order for the mock to return data is needs to be set up to behave as expected given a provided input.
currently in the method under test it is being called like this
buildings = context
.ExecuteQuery<Building>(System.Data.CommandType.StoredProcedure, "dbo.Building_List", Params.ToArray<object>())
.AsQueryable();
Yet in the test the mock context is being setup like
_mockDataContext.Setup(r =>
r.ExecuteQuery<Building>(CommandType.StoredProcedure, "someSproc"))
.Returns(new List<Building>() { new Building() { BuildingId = 1, Title = "1" }}.AsQueryable());
Note what the mock is told to expect as parameters.
The mock will only behave as expected when provided with those parameters. Otherwise it will return null.
Consider the following example of how the test can be exercised based on the code provided in the original question.
[Test]
public void SomeTestName() {
//Arrange
var expected = new List<Building>() { new Building() { BuildingId = 1, Title = "1" }}.AsQueryable();
_mockDataContext
.Setup(_ => _.ExecuteQuery<Building>(CommandType.StoredProcedure, It.IsAny<string>(), It.IsAny<object[]>()))
.Returns(expected);
DataContext.SetTestableInstance(_mockDataContext.Object);
var subject = new BuildingService();
//Act
var actual = subject.GetBuildings(1);
// Assert...
CollectionAssert.AreEquivalent(expected, actual);
}
That said, the current design of the system under test is tightly coupled to a static dependency which is a code smell and makes the current design follow some bad practices.
The static DataContext which is currently being used as a factory should be refactored as such,
public interface IDataContextFactory {
IDataContext CreateInstance();
}
and explicitly injected into dependent classes instead of calling the static factory method
public class BuildingService : IBuildingService {
private readonly IDataContextFactory factory;
public BuildingService(IDataContextFactory factory) {
this.factory = factory
}
public IQueryable<Building> GetBuildings(int propertyId) {
IQueryable<Building> buildings;
using (var context = factory.CreateInstance()) {
var Params = new List<SqlParameter> {
new SqlParameter("#PropertyId", propertyId)
};
buildings = context
.ExecuteQuery<Building>(System.Data.CommandType.StoredProcedure, "dbo.Building_List", Params.ToArray<object>())
.AsQueryable();
}
return buildings;
}
}
This will allow for a proper mock to be created in injected into the subject under test without using a static workaround hack.
[Test]
public void SomeTestName() {
//Arrange
var expected = new List<Building>() { new Building() { BuildingId = 1, Title = "1" }}.AsQueryable();
_mockDataContext
.Setup(_ => _.ExecuteQuery<Building>(CommandType.StoredProcedure, It.IsAny<string>(), It.IsAny<object[]>()))
.Returns(expected);
var factoryMock = new Mock<IDataContextFactory>();
factoryMock
.Setup(_ => _.CreateInstance())
.Returns(_mockDataContext.Object);
var subject = new BuildingService(factoryMock.Object);
//Act
var actual = subject.GetBuildings(1);
// Assert...
CollectionAssert.AreEquivalent(expected, actual);
}
I'm not familiar with mocking. I'd like test if my method GetById return me an object User with an Id. Below the code, I'd like test if the GetById(10) return me an User with id = 10.
I set the moq (I hope it's correct) but how execute the moq ?
Thanks,
[TestMethod]
public void MyMoq()
{
var userMock = new Mock<IUsers>();
userMock.Setup(x => x.GetById(10)).Returns(new User());
//After ?
new Users().GetById(10);
}
public interface IUsers
{
IUser GetById();
}
public IUser GetById(int id)
{
using (var context = ....)
{
//code here
//return user here
}
}
Alright, as I said in comments, it's not clear for me what code you're trying to test. I see two options here.
1) The Users class implements IUsers interface and your intention is to test implementation of GetById(int) method.
In such case you do NOT need to mock the 'Users#GetById(id)' method, you just need to call it and check the result.
The code should look similar to:
interface IUser
{
int Id { get; }
}
class User : IUser
{
public int Id { get;set; }
}
interface IUsers
{
IUser GetById(int id);
}
class Users : IUser
{
public IUser GetById(int id)
{
// TODO: make call db call
// TODO: parse the result
// TODO: and return new User instance with all the data from db
return new User{ Id = id };
}
}
[TestMethod]
public void MyMoq()
{
// TODO: prepare/mock database. That's whole another story.
var users = new Users();
// act
var user = users.GetById(10);
// assert
Assert.AreEqual(10, user.Id);
}
2) Your Users#GetById(int) method is supposed to call the IUsers#GetById(int) and return the result. In such case you need to create mock of IUsers(as you've shown in question) and pass it to Users. The code should be(sorry for possible duplication):
interface IUser
{
int Id { get; }
}
class User : IUser
{
public int Id { get;set; }
}
interface IUsers
{
IUser GetById(int id);
}
class Users : IUser
{
private readonly IUser _users;
public Users(IUser users)
{
_users = users;
}
public IUser GetById(int id)
{
// next line of code is to be tested in unit test
return _users.GetById(id);
}
}
[TestMethod]
public void MyMoq()
{
var usersMock = new Mock<IUsers>();
usersMock.Setup(x => x.GetById(10)).Returns(new User());
var users = new Users(usersMock.Object);
// act
var user = users.GetById(10);
// assert
Assert.AreEqual(10, user.Id);
}
p.s. Could be useful to take a look at moq tutorial and The Art of Unit Testing book, Part 2 - Core techniques(page 47) - stubs, mocks, etc.
I don't quite sure what you want to test. You also has Mock class with some methods that you don't describe.
However, answering your question about mocking. Consider this class:
public class MyMoq : IUsers
{
private readonly Mock<IUsers> userMock;
public MyMoq(Mock<IUsers> userMock){
this.userMock = userMock;
}
[TestMethod]
public IUser GetById()
{
userMock.Setup(x => x.GetById(10)).Returns(new User());
//After ?
return new UsersDb().GetById(10);
}
}
To use it:
MyMoq moq = new MyMoq(new Mock<IUsers>());
User u = moq.GetById();
My assumption in this example is Mock<IUsers> is a repository and MyMoq is a service class. Also, IUser is an Entity Interface, and IUsers is a service interface.
To test userMock.Object should return the actual mocked IUsers object.
var userMock = new Mock<IUsers>();
userMock.Setup(x => x.GetById(10)).Returns(new User());
var mockobject = userMock.Object;
//Returns your mocked new User() instance
var newUserObject = mockobject.GetById(10);
In the above code, newUserObject has only created a new instance of User.
To test your GetById method, you need to call it again and Assert.
Assert.AreEqual(newUserObject.GetById(20).ID, 20); //Assume User has a property ID
Suggestion: It should be possible to have a better way to create the User instance.
GetById should be in it's own class (probably called Users) if that is what is being tested. Users could then accept a context in the constructor. Then mock this context to return stubbed data.
So in summary
Class Users implementing IUsers
Users has a constructor with parameter IContext (or whatever it would be called here)
Test class would mock IContext but not IUsers.
Call users.GetById and check the output is correct.
The way you would set up your context depends on what type of context it is, but see https://cuttingedge.it/blogs/steven/pivot/entry.php?id=84.
I am new with Moq and TDD and what I am trying to do is to set up method on repository interface.
Here is full story.
I have a domain entity class called Tenant with property BusinessIdentificationNumber
public class Tenant:EntityBase<Tenant>,IAggregateRoot
{
...
public string BusinessIdentificationNumber {get;set;}
...
}
Next I have repository for this entity which interface is like
public interface IRepository<T>
{
...
T FindBy(Func<T,bool> func);
...
}
where the problem is, I use a domain service which holds the rules for creating a tenant and is like
public class TenantCreationService:ITenantCreationService
{
public TenantCreationService(IRepository<Tenant> tenantRepository){...}
public void CreateTenant(Tenant tenant)
{
//from here there is call to IRepository<Tenant>.FindBy(funcMethod);
}
}
And in unit testing where I am testing the TenantCreationService I mock the repository passed to constructor, but I would like to test the feature :
when tenant with BusinessIdentificationNumber already exists in storage or session it should be returned.
So I was trying to do it like
repositoryMock.Setup(x=>x.FindBy(It.Is<Tenant>(t=>t.BusinessIdentificationNumber
== _tenantInTest.BusinessIdentificationNumber))).Returns(_tenantInTest)
but it does not compile. You know what I want to do?
EDIT:
when i try to compile the snippet below
repositoryMock.Setup(e => e.FindBy(t => t.BusinessNumber == _validTenant.BusinessNumber)).Returns(
_validTenant);
i get exception
Unsupported expression: t => (t.BusinessNumber == value(DP.IPagac.UnitTests.DP.IPagac.Module.TenantManagement.TenantDomainServiceTests)._validTenant.BusinessNumber)
I think what you are trying the acheive is this (removed some things that were extraneous for example and created ITenent so it can be mocked dynamically):
[TestFixture]
public class Test
{
[Test]
public void CreateTenentAlreadyExistsTest()
{
var tenentMock = new Mock<ITenant>();
var repoMock = new Mock<IRepository<ITenant>>();
tenentMock.Setup(t => t.BusinessIdentificationNumber).Returns("aNumber");
repoMock.Setup(r => r.FindBy(It.Is<System.Func<ITenant, bool>>(func1 => func1.Invoke(tenentMock.Object)))).Returns(tenentMock.Object);
var tenantCreationService = new TenantCreationService(repoMock.Object);
tenantCreationService.CreateTenant(tenentMock.Object);
tenentMock.VerifyAll();
repoMock.VerifyAll();
}
}
public interface ITenant
{
string BusinessIdentificationNumber { get; set; }
}
public class Tenant : ITenant
{
public string BusinessIdentificationNumber { get; set; }
}
public interface IRepository<T>
{
T FindBy(System.Func<T, bool> func);
}
public class TenantCreationService : ITenantCreationService
{
private readonly IRepository<ITenant> _tenantRepository;
public TenantCreationService(IRepository<ITenant> tenantRepository)
{
_tenantRepository = tenantRepository;
}
public void CreateTenant(ITenant tenant)
{
var existingTenant =
_tenantRepository.FindBy(t => t.BusinessIdentificationNumber == tenant.BusinessIdentificationNumber);
if (existingTenant == null)
{
//do stuff
}
}
}
public interface ITenantCreationService
{
void CreateTenant(ITenant tenant);
}
"when tenant with BusinessIdentificationNumber already exists in storage or session it should be returned." - from this test description I understood that this behavior you should test in repository class not in on service class
In unit test for services you should not test data accesses layer I mean your repositories,
you should just verify that the repository method FindBy was called.
and my suggest Create ITenantRepositry that derive from IRepository interface and from base class Repostiry.