I declared a class LogManager and an interface ILogManager, and has a method LoggerError, this method use ILogger (DI) to logerror and do other things.
There is a class A (DI ILogClass ) and declare a method funA(), and funA() will use _LogManager.LoggerError("test message").
When do I unit test with mock ?
How to Verify _LogManager.LoggerError("test message") ?
If I just use ILogger in class A, I can Verify with :
loggerMock.Verify(l => l.Log(LogLevel.Error,It.IsAny<EventId>(),
It.Is<object>(o => o.ToString().Contains("test message")),null,It.IsAny<Func<object, Exception, string>>()), Times.Once);
But not support with ILogManager mock.
public class LoggerManager<TCategoryName> : ILoggerManager<TCategoryName>
{
private readonly ILogger<TCategoryName> _logger;
public LoggerManager(ILogger<TCategoryName> logger)
{
this._logger = logger;
}
public void LogError(string message, LoggerErrorType type)
{
var errorLogger = NLog.LogManager.GetLogger(loggerName);
errorLogger.Error(message);
}
}
class A
{
....DI
public void Test()
{
_loggerManager.LogError("test message")
}
}
UT:
public void TestUT()
{
var loggerMock = new Mock ILoggerManager A>>();
var service = ServiceFactory.Create<A>(loggerMock);
service.Test();
//how to Verify logerror message?
}
Your LoggerManager<TCategoryName> is just a wrapper over the ILogger<TCategoryName> and thus you can just mock ILogger<TCategoryName> and verify the same as you have already done and that should work just fine.
Though while making the actuall call to SUT you will have to dependency inject the LoggerManager<TCategoryName> accordingly
Related
My project requires unit testing. I am using constructor dependency injection in my controller. When I mock the injected dependency object in my unit testing project and call it in a test method. Returns null in all cases.
Controller Class:
public class Owner:Controller
{
private readonly IComRepository repository;
private readonly DbContext context;
public Owner(IComRepository repository, DbContext context)
{
this.repository=repository;
this.context=context;
}
[HttpGet("GetAllTypes")]
public async Task<IActionResult> GetAllTypes()
{
var ownerTypes=repository.GetTypes();
return Ok(ownerTypes);
}
}
My Repository Class
public Interface IComRepository
{
IList<Type> GetTypes();
}
public Class ComRepository : IComRepository
{
private readonly DbContext context;
public ComRepository(DbContext context)
{
this.context=context;
}
public IList<Type> GetTypes()
{
var allTypes= context.Types.ToList();
return allTypes;
}
}
Now I need to test the GetAllTypes methods in my controller class. My Test Class is below mentioned:
using moq;
[TestClass]
public Class OwnerTest
{
public OwnerTest()
{
var mockIcomrepo = new Mock<IComRepository>();
var mockDbcontext = new Mock<Dbcontext>();
OwnerController owner = new OwnerController(mockDbContext.Object, mockIcomrepo.Object);
}
[TestMethod]
public void GetTypes()
{
var allTypes= owner.GetAllTypes(); //It's not trigger to my controller
Assert.AreEqual(5,allTypes.count());
}
}
How can I do it? Any one know the answer for this question.
As #Nkosi mentioned you have to use moq setup. Define your mocks outside constructor and initalize them in test class's constructor.
using moq;
[TestClass]
public Class OwnerTest
{
private readonly IComRepository _mockRepository;
private readonly OwnerControler _ownerController;
//your mock data
private readonly IList<Type> mockData;
public OwnerTest()
{
_mockRepository= new Mock<IComRepository>();
_ownerController = new OwnerController(mockDbContext.Object, mockIcomrepo.Object);
mockData=new IList<Type>{"Data1","Data2","Data3","Data4","Data5"};
}
//choose better names for testing a method
//Naming convention like this MethodName_StateUnderTest_ExpectedResult;
[TestMethod]
public void GetAllTypes()
{
_mockRepository.Setup(p=>p.GetAllTypes()).Returns(mockData);
var result= _ownerController.GetAllTypes();
var okResult=Assert.IsType<OkObjectResult>(result)
var returnTypes=Assert.IsAssignableFrom<IList<Type>>(okResult.Value);
Assert.AreEqual(5,returnTypes.count());
}
}
Also, why you inject your dbcontext to controller?your repository should depend dbcontext not controller.
I am using XUnit and need to perform some action before running a test suit. so, I try to use IClassFixture feature of XUnit. but I cannot find a way to inject dependencies into the Fixture class. my code structure is such as below:
public class MyFixture
{
IDependency _dep;
public MyFixture(IDependency dep)
{
_dep = dep;
}
void DoSomeJob()
{
//// some code there
dep.DoSome();
}
}
And this is my test class code:
public class MyTest : IClassFixture<MyFixture>
{
[Fact]
public void test_my_code()
{
////simply just test the code
}
}
but when I run the test I am getting the exception
Xunit.Sdk.TestClassException Class fixture type 'MyFixture' had one or more unresolved constructor
Your Fixture class depends on IDependency dep, which has not been configured. You could use the Fixture class to setup a service provider; However it is not the best solution, as you have to end up using service locator patter such as
serviceProvider.GetRequiredService<T>()
Suggest to use xunit.di, it is an extension built into xunit framework to support constructor dependency injection, which allows us to achieve Inversion of Control (IoC) between test classes and their dependencies.
Install-Package Xunit.Di
To use xunit.di:
Install the xunit.di nuget package
Create a Setup.cs class to configure dependencies, (optional) and inherits the Xunit.Di.Setup.cs
Configure dependencies in the Setup.cs class.
Find full instructions and demos from xunit.di GET-STARTED
Your test project has the following:
Setup class that has a public IServiceProvider, which configures all the dependencies
Test class with constructor injecting the dependencies
Your Setup.cs class looks like below:
private IServiceProvider _services;
private bool _built = false;
private readonly IHostBuilder _defaultBuilder;
public Setup()
{
_defaultBuilder = Host.CreateDefaultBuilder();
}
public IServiceProvider Services => _services ?? Build();
private IServiceProvider Build()
{
if (_built)
throw new InvalidOperationException("Build can only be called once.");
_built = true;
_defaultBuilder.ConfigureServices((context, services) =>
{
services.AddSingleton<TextReaderService>();
services.AddSingleton<IDependency, DependencyImpl>();
// where DependencyImpl implements IDependency
// ... add other services needed
});
_services = _defaultBuilder.Build().Services;
return _services;
}
Then your test class looks like below:
public class MyTest
{
private readonly IDependency _dependency;
public MyTest(IDependency dependency)
{
_dependency = dependency;
}
[Fact]
public void test_my_code()
{
var result = _dependency.DoStuff();
Assert.NotNull(result);
////simply just test the code
}
}
public class TestStartup : Startup
{
private readonly Mock<ICarService> _carServiceMock;
public TestStartup(IConfiguration configuration) : base(configuration)
{
_carServiceMock = new Mock<ICarService>();
}
public override void ConfigureMyServices(IServiceCollection services)
{
services.AddSingleton(_carServiceMock.Object);
}
public override void ConfigureDatabase(IServiceCollection services)
{
services.AddDbContext<CarContext>(options => options.UseInMemoryDatabase("CarDb"));
services.AddTransient<DataSeed>();
}
}
public class TestFixture: IDisposable, ICollectionFixture<TestFixture>
{
public TestFixture()
{
_server = new TestServer(new WebHostBuilder()
.UseStartup<TestStartup>()
.UseEnvironment("Development"));
_client = _server.CreateClient();
}
}
Inside Controller I'm using ICarService which is using CarContext to retrieve data from the Db.
public class CarController
{
private readonly ICarService _carService;
public CarController(ICarService carService)
{
_carService = carService;
}
[HttpGet]
public async Task<IActionResult> Get([FromRoute] int id)
{
var contact = await _carService.GetAsync(id); **// this is always null**
}
}
My question is:
Since this is an integration test, do I need to mock ICarService in the first place and if so, what I'm doing wrong here?
If you are testing how the CarService class interacts with the database then you shouldn't be mocking it.
What you want to do is use the real CarService implementation and let dependency injection add the InMemoryDatabase into that class as the CarContext parameter.
So, remove the Mock<ICarService> and register the real one instead.
Why is it returning null?
In you example, when you call the method _carService.GetAsync(id) it is calling the mock class. But you haven't Setup any methods on the mock so any calls will return null.
You need to add the following to cause the mocked method to return a value:
_carService.Setup(cs => cs.GetAsync(It.IsAny<int>()).Returns(1);
But this would not call the in memory database as you are using a mock for CarService.
I'm trying to utilize Ninject to help me build up a possible tree of service classes. I'd like to inject an ILogger instance using InCallScope so any child service class would use the same logger.
The logger implementation has a property called RootService, which would point to the upper-most service class instance which uses the logger. I would use information from it when categorizing logged events according to from which service class it has come from (child classes would not define another "log scope", hence I use InCallScope).
Can I fine-tune the ILogger Ninject binding so that I could have kind of a callback when the ILogger instance is activated, and I had there the instance too, into which it recently got injected? So there I could set the RootService property of my logger.
There's is the OnActivation binding extension which is a callback which is executed when ILogger is instanciated.
So you can do the following:
public class Test
{
[Fact]
public void Foo()
{
var kernel = new StandardKernel();
kernel.Bind<Service>().ToSelf();
kernel.Bind<Logger>().ToSelf()
.OnActivation((ctx, logger) =>
logger.Initalize(ctx.Request.Target.Member.DeclaringType));
var service = kernel.Get<Service>();
service.Logger.RootService.Should().Be(typeof(Service));
}
}
public class Logger
{
public Type RootService { get; private set; }
public void Initalize(Type rootService)
{
this.RootService = rootService;
}
}
public class Service
{
public Logger Logger { get; private set; }
public Service(Logger logger)
{
Logger = logger;
}
}
However, IContext does not provide access to the "parent" instance, so you can only access the type it's injected into, but not the instance.
Also, if that should be enough, there's no need to actually use the OnActivation extension, you should also be able to just do it like this:
public class Test
{
[Fact]
public void Foo()
{
var kernel = new StandardKernel();
kernel.Bind<Service>().ToSelf();
kernel.Bind<Logger>().ToSelf()
.WithConstructorArgument(
typeof(Type),
ctx => ctx.Request.Target.Member.DeclaringType);
var service = kernel.Get<Service>();
service.Logger.RootService.Should().Be(typeof(Service));
}
}
public class Logger
{
private readonly Type _rootService;
public Logger(Type rootService)
{
_rootService = rootService;
}
public Type RootService
{
get { return _rootService; }
}
}
public class Service
{
public Logger Logger { get; private set; }
public Service(Logger logger)
{
Logger = logger;
}
}
Hello I have code like below and use xUnit. I would like to write TestClass to test my interface. Could you tell my how can I:
inject different services to test class by DependencyInjection and run test for this services.
prepare object to inject with Autofixture and AutoMoq. Before inject i would like to create services like
I want to do somethink like this :
public ServiceTestClass
{
private ISampleService sut;
public ServiceTestClass(ISampleService service) {
this.sut = service;
}
[Fact]
public MyTestMetod() {
// arrange
var fixture = new Fixture();
// act
sut.MakeOrder();
// assert
Assert(somethink);
}
}
public class SampleService : ISampleService // ande few services which implements ISampleService
{
// ISampleUow also include few IRepository
private readonly ISampleUow uow;
public SampleService(ISampleUow uow) {
this.uow = uow;
}
public void MakeOrder() {
//implementation which use uow
}
}
It isn't particularly clear what you're asking, but AutoFixture can serve as an Auto-mocking Container. The AutoMoq Glue Library is one of many extensions that enable AutoFixture to do that. Others are AutoNSubstitute, AutoFakeItEasy, etc.
This enables you to write tests like this one:
[Fact]
public void MyTest()
{
var fixture = new Fixture().Customize(new AutoMoqCustomization());
var mock = fixture.Freeze<Mock<ISampleUow>>();
var sut = fixture.Create<SampleService>();
sut.MakeOrder();
mock.Verify(uow => /* assertion expression goes here */);
}
If you combine it with the AutoFixture.Xunit2 Glue Library, you can condense it to this:
[Theory, MyAutoData]
public void MyTest([Frozen]Mock<ISampleUow> mock, SampleService sut)
{
var sut = fixture.Create<SampleService>();
sut.MakeOrder();
mock.Verify(uow => /* assertion expression goes here */);
}