I am trying to understand how mocking works in Xunit with AutoFixture. I have created Service and Repository classes and their interfaces. Mocked method should pass value which is different from default value.
Mocked method always pass default values instead of values which i am writing in ".Returns()". I have tried AutoConfiguredMoqCustomization but it provides completely random values which i can't get back.
Repository.cs
public class Repository : IRepository
{
public int GetInt()
{
return 999;
}
}
Service.cs
public class Service : IService
{
private readonly Repository _repository;
public Service()
{
_repository = new Repository();
}
public string GetStringFromInt()
{
return _repository.GetInt().ToString();
}
}
Test
[Fact]
public void Test()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var repositoryMock = fixture.Create<Mock<IRepository>>();
var service = fixture.Create<Service>();
repositoryMock.Setup(x => x.GetInt()).Returns(1);
var act = service.GetStringFromInt();
Assert.Equal("1", act);
}
As you see value by default in Repository is 999 and I am expecting 1 from repositoryMock but result is "999" instead of "1".
Ow I have understood my problem. When I declare parameters with auto moq testing service must be AFTER all mocked repositories
Test
[Theory, AutoMoqData]
public void Test([Frozen] Mock<IRepository> repositoryMock, Service service)
{
...
}
Attribute
public class AutoMoqDataAttribute : AutoDataAttribute
{
public AutoMoqDataAttribute() : base(GetDefaultFixture)
{
}
private static IFixture GetDefaultFixture()
{
return new Fixture().Customize(new AutoMoqCustomization());
}
}
You should freeze your mock first. When you call Create on AutoFixture, it will create you a new instance every time. Try the following in the modified code (where you are using an interface of the type in your constructor).
public class ServiceTests
{
private readonly IFixture fixture = new Fixture().Customize(new AutoMoqCustomization());
public ServiceTests()
{
fixture.Register<IService>(() => fixture.Create<Service>());
}
[Fact]
public void Test()
{
// Arrange
var repositoryMock = fixture.Freeze<Mock<IRepository>>();
repositoryMock.Setup(x => x.GetInt()).Returns(1);
var service = fixture.Create<IService>();
// Act
var act = service.GetStringFromInt();
// Verify
Assert.Equal("1", act);
}
}
To check that you have set up autofixture correctly, you can try the following in the unit test in future.
var repo1 = fixture.Create<IRepository>();
var repo2 = fixture.Create<IRepository>();
Assert.Equal(repo1.GetHashCode(), repo2.GetHashCode());
If the above fails, that indicates that you have not frozen a type. These lines of code have saved me so much head scratching in the past...
You are doing DI wrong, you are not injecting Repository into Your serice.
Try like this.
public class Repository : IRepository
{
public int GetInt()
{
return 999;
}
}
public class Service : IService
{
IRepository Repository;
public Service(IRepository repository)
{
this.Repository = repository;
}
public string GetStringFromInt()
{
return Repository.GetInt().ToString();
}
}
Now when you mock IRepository, you can add it to Service.
You are using a new Repository() in constructor, so you are using that implementation
Related
I have a controller with the following signature:
public CustomerTypeController(
IHttpContextAccessor accessor,
IPrincipalProvider provider,
IMapper mapper,
ILogger<CustomerTypeController> logger,
ICustomerTypeService customerTypeService)
{ }
I also set up an AutoDataAttribute:
public class AutoMoqDataAttribute : AutoDataAttribute
{
public AutoMoqDataAttribute()
: base(() =>
{
var fixture = new Fixture().Customize(new CompositeCustomization(
new AutoMoqCustomization(),
new SupportMutableValueTypesCustomization()));
fixture.Behaviors.OfType<ThrowingRecursionBehavior>()
.ToList()
.ForEach(x => fixture.Behaviors.Remove(x));
fixture.Behaviors.Add(new OmitOnRecursionBehavior());
return fixture;
})
{ }
}
For now my Theory looks like this:
[Theory, AutoMoqData]
public void GetWhenHasCustomerTypesShouldReturnOneCustomerType(
IFixture fixture,
[Frozen] Mock<ICustomerTypeService> service,
CustomerTypeController sut)
{
//Arrange
var items = fixture.CreateMany<Model.CustomerType>(3).ToList();
//Act
var result = sut.Get(1);
//Assert
Assert.IsType<OkResult>(result);
}
Do I need to setup the service with the items before getting an item from the controller? If yes, how is the service set up?
Use the [NoAutoProperties] attribute to decorate the controller parameter in the test method.
Refer to this answer for details.
I've been trying to write a few tests in NUnit for my generic methods, without success. I hope I can make my situation clear, since I had to heavily paraphrase my code.
DoBusinessLogic() is the method I want to test. It calls two other methods from the base class:
public class MySvc : BaseSvc, IMySvc
{
private readonly IMyRepo _repo;
private readonly IMyConnectorClass _connector
public MySvc(IMyRepo repo) : base(repo)
{
_repo = repo;
_connector = _repo.GetConnector();
}
public async Task DoBusinessLogic(int id1, int id2){
bool doesFirstObjectExist = await CheckMainObjExists<Foo>(id1, _connector);
await CheckSubObjExists<Bar>(id2, _connector);
// further business logic
}
}
Those methods, in turn, call the same repository method, but have different logic after it:
public abstract class BaseSvc : IBaseSvc
{
private readonly IBaseRepo _repo
protected BaseSvc(IBaseRepo repo)
{
_repo = repo;
}
protected async Task<bool> CheckMainObjExists<T>(int? id, IMyConnectorClass connector)
{
return await _repo.GetObjectByIdAsync<T>(Id, connector) != null;
}
protected async Task CheckSubObjExists<T>(int? id, IMyConnectorClass connector)
{
if (await _repo.GetObjectByIdAsync<T>(Id, connector) == null)
{ throw new Exception("Object not found!"); }
}
}
Next, I want to write unit a test for DoBusinessLogic() in the MySvc class. Unfortunately, it seems I can't mock the responses from the repository.
[TestFixture]
public class MySvcTests
{
private MySvc _svc;
private Mock<IMyRepo> _repoMock;
private Mock<IMyConnectorClass> _connectorMock;
[SetUp]
public void SetUp()
{
_repoMock = new Mock<IMyRepo>() {};
_connectorMock = new Mock<IMyConnectorClass>();
_repo.SetUp(r => r.GetConnector()).Return(_connectorMock.Object);
_svc = new MySvc(_repoMock);
}
/*
My intent in this test, is to make CheckMainObjExists() pass,
but make CheckSubObjExist() fail.
*/
[Test]
public async Task DoBusinessLogic_If2ndObjectNotExist_ThrowException()
{
// This should return an object
_repoMock.Setup(r => r.GetObjectByIdAsync<Foo>(It.IsAny<int>(), _connectorMock.Object))
.ReturnsAsync(new Foo());
// This should return null
_repoMock.Setup(r => r.GetObjectByIdAsync<Bar>(It.IsAny<int>(), _connectorMock.Object))
.ReturnsAsync((Bar) null);
Assert.Throws<Exception>(await _svc.DoBusinessLogic());
}
}
However, when I run the test, both methods that I set up for my mock repo return null, whereas I expect a "true" from the first.
I do not know where the problem is situated, but I have my suspicions:
Is it possible to setup a method, using a mocked object as a parameter? In this case, is it possible to use _connectorMock.Object as a setup parameter?
Is it possible to setup the same generic method multiple times, but for a different type each time? It's first setup for Foo, then for Bar.
I just tested this code and it runs as expected. Now I had to make a lot of assumptions just to get the code to compile and run which would mean that my test of your code is flawed as I may have fixed something that was omitted in your example.
I made no changes to your test setup code, which worked.
[TestClass]
public class MySvcTests {
[TestMethod]
[ExpectedException(typeof(Exception))]
public async Task DoBusinessLogic_If2ndObjectNotExist_ThrowException() {
var _repoMock = new Mock<IMyRepo>() { };
var _connectorMock = new Mock<IMyConnectorClass>();
_repoMock.Setup(r => r.GetConnector()).Returns(_connectorMock.Object);
var _svc = new MySvc(_repoMock.Object);
// This should return an object
_repoMock.Setup(r => r.GetObjectByIdAsync<Foo>(It.IsAny<int>(), _connectorMock.Object))
.ReturnsAsync(new Foo());
// This should return null
_repoMock.Setup(r => r.GetObjectByIdAsync<Bar>(It.IsAny<int>(), _connectorMock.Object))
.ReturnsAsync((Bar)null);
await _svc.DoBusinessLogic(0, 0);
}
}
I'm trying to mock SignalR broadcasting present in ApiController(WebApi), but unable to complete test case, below is my code
SignalRHub
public class HubServer : Hub { }
ApiControllerWithHub
public abstract class ApiControllerWithHubController<THub> : ApiController where THub : IHub
{
Lazy<IHubContext> hub = new Lazy<IHubContext>(() => GlobalHost.ConnectionManager.GetHubContext<THub>());
protected IHubContext Hub
{
get { return hub.Value; }
}
}
Controller (Method to Mock)
public class NotificationController : ApiControllerWithHubController<HubServer>
{
[HttpPost]
public HttpResponseMessage SendNotification(NotificationInput notification)
{
Hub.Clients.Group("GroupName").BroadcastCustomerGreeting("notification");
}
}
I'm writing following unit test with the help of Mock SignalR Post, I'm stuck here because this is SignalR call from controller not from SignalR Hub.
MockTest
public interface IClientContract
{
void BroadcastCustomerGreeting(string message);
}
[TestMethod]
public void SendNotificationTest()
{
NotificationInput notificationInput = new NotificationInput();
notificationInput.CId = "CUST001";
notificationInput.CName = "Toney";
// Arrange
var mockClients = new Mock<IHubConnectionContext<dynamic>>();
var mockGroups = new Mock<IClientContract>();
// Act.
mockGroups.Setup(_ => _.BroadcastCustomerGreeting("notification")).Verifiable();
mockClients.Setup(_ => _.Group("GroupName")).Returns(mockGroups.Object);
// I'm stuck here
var controller = new NotificationController();
// Act
HttpResponseMessage actionResult = controller.SendNotification(notificationInput);
}
Any help is appreciated to complete/correct this unit test.
Redesign needed. Base ApiController tightly coupled to static accessor of the hub context. This needs to be refactored out into its own service to allow for more flexibility via constructor injection.
public interface IHubContextProvider {
IHubContext Hub { get; }
}
public class HubContextProvider<THub> : IHubContextProvider where THub : IHub {
Lazy<IHubContext> hub = new Lazy<IHubContext>(() => GlobalHost.ConnectionManager.GetHubContext<THub>());
public IHubContext Hub {
get { return hub.Value; }
}
}
Controllers now need to be refactored to explicitly expose its dependencies.
public abstract class ApiControllerWithHubController<THub> : ApiController where THub : IHub {
private readonly IHubContext hub;
public ApiControllerWithHubController(IHubContextProvider context) {
this.hub = context.Hub;
}
protected IHubContext Hub {
get { return hub; }
}
}
public class NotificationController : ApiControllerWithHubController<HubServer> {
public NotificationController(IHubContextProvider context)
: base(context) {
}
[HttpPost]
public IHttpActionResult SendNotification(NotificationInput notification) {
Hub.Clients.Group("GroupName").BroadcastCustomerGreeting("notification");
return Ok();
}
}
Test can now be exercised with necessary mocks of dependencies.
[TestMethod]
public void _SendNotificationTest() {
// Arrange
var notificationInput = new NotificationInput();
notificationInput.CId = "CUST001";
notificationInput.CName = "Toney";
var groupName = "GroupName";
var message = "notification";
var mockGroups = new Mock<IClientContract>();
mockGroups.Setup(_ => _.BroadcastCustomerGreeting(message)).Verifiable();
var mockClients = new Mock<IHubConnectionContext<dynamic>>();
mockClients.Setup(_ => _.Group(groupName)).Returns(mockGroups.Object).Verifiable();
var mockHub = new Mock<IHubContext>();
mockHub.Setup(_ => _.Clients).Returns(mockClients.Object).Verifiable();
var mockHubProvider = new Mock<IHubContextProvider>();
mockHubProvider.Setup(_ => _.Hub).Returns(mockHub.Object);
var controller = new NotificationController(mockHubProvider.Object);
// Act
var actionResult = controller.SendNotification(notificationInput);
//Assert
mockClients.Verify();
mockGroups.Verify();
mockHub.Verify();
}
Just make sure to register new service with DI container so that it can be injected into dependent controllers.
With the redesign the base controller can be removed all together and the hub provider used directly. This is assuming that there was not any other reason to have the base controller.
I am doing a simple unit test where when creating a Course, the Title field cannot be empty. I am having to test it with a service class that has Dependency Injection with UnitOfWork. When I debug my test, I am getting an Exception error of Can not instantiate proxy of class: ContosoUniversity.Models.CourseRepository I looked into the error, but am not able to understand how to fix the issue and the Assert statement?
Error Message Display Image
CourseRepository
public class CourseRepository : GenericRepository<Course>
{
public CourseRepository(SchoolContext context)
: base(context)
{
}
UnitOfWork
public class UnitOfWork : IDisposable, IUnitOfWork
{
private SchoolContext context = new SchoolContext();
private GenericRepository<Department> departmentRepository;
private CourseRepository courseRepository;
public CourseRepository CourseRepository
{
get
{
if (this.courseRepository == null)
{
this.courseRepository = new CourseRepository(context);
}
return courseRepository;
}
}
public virtual CourseRepository GetCourseRepository()
{
if (this.courseRepository == null)
{
this.courseRepository = new CourseRepository(context);
}
return courseRepository;
}
CourseService
public class CourseService : ICourseService
{
private IUnitOfWork unitOfWork;
public CourseService (IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
public void Create(Course course)
{
unitOfWork.GetCourseRepository().Insert(course);
unitOfWork.Save();
}
public Course GetCourseByID(int id)
{
return unitOfWork.GetCourseRepository().GetByID(id);
}
TestMethod
[TestMethod]
public void TestMethod1()
{
var course = new Course
{
CourseID = 2210,
Title = string.Empty,
Credits = 3,
DepartmentID = 1
};
Mock<CourseRepository> mockRepo = new Mock<CourseRepository>();
mockRepo.Setup(m => m.GetByID(course.CourseID)).Returns(course);
var mockUnit = new Mock<IUnitOfWork>();
mockUnit.Setup(x => x.GetCourseRepository()).Returns(mockRepo.Object);
var myService = new CourseService(mockUnit.Object);
myService.Create(course);
//var error = _modelState["Title"].Errors[0];
//Assert.AreEqual("The Title field is required.", error.ErrorMessage);
//mockRepo.Setup(x => x.Insert(course));
}
The error says that the CourseRepository can not be initialized because it does not have parameter less constructor. Mocking framework looks for parameter less constructor first to create mock object.
If your class does not have parameterless constructor then you need to pass those parameters when you create Mock. In your case mock of CourseRepository would be created as following.
var repositoryMock = new Mock<CourseRepository>(null);
Instead of null, you can pass mock objects of the constructor parameters also.
Just use the interface when mocking.
Mock<ICourseRepository> mockRepo = new Mock<ICourseRepository>();
mockRepo.Setup(m => m.GetByID(course.CourseID)).Returns(course);
Alternatively, if your class has an internal parameterless constructor, you need to add the InternalsVisibleTo attribute to assembly.
In case of Moq, add this:
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
Or this, if you need an strong key
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2,PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
In my case, adding the [Frozen] attribute to my mock helped solve this problem.
I was also having the "cannot instantiate proxy of class error", but in my case, I was doing something like this:
[Theory, AutoMoqDate]
public async void Should_DoThis_When_ThatHappens(
Fixture fixture,
Mock<TroublesomeClass> troublesomeObject
){
var someResult = SomeObject();
troublesomeObject.Setup(o => o.SomeMethodAsync().ReturnsAsync(someResult);
// Code bellow is irrelevant...
}
For me, troublesomeObject's method was called in my suite's method, and when it got to SomeMethodAsync() is when the exception occurred.
When I added the [Frozen] tag before the troublesome object, the issue subsided.
I have a service set up as follows:
public interface IMyService
{
void AddCountry(string countryName);
}
public class MyService : IMyService
{
public void AddCountry(string countryName)
{
/* Code here that access repository and checks if country exists or not.
If exist, throw error or just execute. */
}
}
Test.cs
[TestFixture]
public class MyServiceTest
{
[Test]
public void Country_Can_Be_Added()
{ }
[Test]
public void Duplicate_Country_Can_Not_Be_Added()
{ }
}
How do I test AddCountry and moq the repository or service. I'm really not sure what to do here or what to mock. Can someone help me out?
Frameworks I'm using:
NUnit
Moq
ASP.NET MVC
And why would you need to use moq? You don't need to mock IService. In your case you can write your test like this:
[Test]
public void Country_Can_Be_Added()
{
new MyService().AddCountry("xy");
}
[Test]
public void Duplicate_Country_Can_Not_Be_Added()
{
Assert.Throws<ArgumentException>(() => new MyService().AddCountry("yx"));
}
You would need to mock the IRepository if you had a scenario like this:
interface IRepository { bool CanAdd(string country); }
class MyService : IService
{
private IRepository _service; private List<string> _countries;
public IEnumerable<string> Countries { get { return _countries; } }
public X(IRepository service) { _service = service; _countries = new List<string>(); }
void AddCountry(string x)
{
if(_service.CanAdd(x)) {
_conntires.Add(x);
}
}
}
And a test like this:
[Test]
public void Expect_AddCountryCall()
{
var canTadd = "USA";
var canAdd = "Canadd-a";
// mock setup
var mock = new Mock<IRepository>();
mock.Setup(x => x.CanAdd(canTadd)).Returns(false);
mock.Setup(x => x.CanAdd(canAdd)).Returns(true);
var x = new X(mock.Object);
// check state of x
x.AddCountry(canTadd);
Assert.AreEqual(0, x.Countires.Count);
x.AddCountry(canAdd);
Assert.AreEqual(0, x.Countires.Count);
Assert.AreEqual(0, x.Countires.Count);
Assert.AreEqual(canAdd, x.Countires.First());
// check if the repository methods were called
mock.Verify(x => x.CanAdd(canTadd));
mock.Verify(x => x.CanAdd(canAdd));
}
You test the concrete MyService. If it takes a dependency (say on IRepository) you would create a mock of that interface and inject it into the service. As written, no mocks are needed to test the service.
The point of creating the IMyService interface is to test other classes that depend on MyService in isolation. Once you know Repository works, you don't need to test it when you're testing MyService (you mock or stub it out). Once you know MyService works, you don't need to test it when you're testing MySomethingThatDependsOnMyService.