How to NUnit test controller with multiple repositories [closed] - asp.net-core

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I have a .net core API with a controller that handles multiple tables in the SQL database and I am using repository pattern design for best practice.
My Home controller's constructor injection looks like this:
private IUploadRepository _uploadRepository;
private ISalesRepository _salesRepository;
private ITRSalesRepository _trsalesRepository;
private ILocalPurchaseRepository _localRepository;
public HomeController(
IUploadRepository uploadRepository,
ISalesRepository salesRepository,
ITRSalesRepository trsalesRepository,
ILocalPurchaseRepository localRepository
)
{
this._uploadRepository = uploadRepository;
this._salesRepository= salesRepository;
this._trsalesRepository= trsalesRepository;
this._localRepository= localRepository;
}
[HttpPost]
public IActionResult PostUpload([FromBody] UploadModel upload)
{
uploadRepository.Add(upload); // the uploadRepository will save to db
return Created("Post", upload)
}
I have added the DI for these repositories in the StartUp.cs and I have verified that the Home controller (method) is behaving as expected. It is able to read/write to SQL db.
My question is, how can I use NUnit test to test this Home controller's Post action method? I have multiple CRUD methods that utilize these repository so in general I'd want to NUnit test them all.
I've tried to use constructor injection for the Home-Test-Class but that doesn't work.
Thank you for your help!
Uddate:
I've added a Post method as a test I would like to NUnit test on.

To unit test HomeController, you don't need to instantiate the external dependencies. You can have them as Mock Objects. There are lot of mocking frameworks out there that can do the job for you.
"Your goal is to unit test the HomeController only and test the functionalities related to it." Use mock or stub objects to minimize the number of external dependencies, so the test is focused on testing one thing only.
Following is a simple example to test your controller. I have also created a dummy project, you can see the code here NewEmployeeBuddy.CoreAPI:
using Microsoft.AspNetCore.Mvc;
using Moq;
using System.Collections.Generic;
using Xunit;
namespace UnitTestDemo.Tests.Controllers
{
public class HomeControllerTest
{
#region Properties
protected readonly Mock<IUploadRepository> uploadMockRepository;
protected readonly Mock<ISalesRepository> salesMockRepository;
protected readonly Mock<ITRSalesRepository> trsalesMockRepository;
protected readonly Mock<ILocalPurchaseRepository > localMockRepository;
protected readonly HomeController controllerUnderTest;
#endregion
#region Constructor
public HomeControllerTest()
{
//Don't rely on the dependency injection. Define your mock instances for the dependencies.
uploadMockRepository= new Mock<IUploadRepository>();
uploadMockRepository.Setup(svc => svc.GetAllEmployees()).Returns();
salesMockRepository= new Mock<ISalesRepository>();
trsalesMockRepository= new Mock<ITRSalesRepository>();
localMockRepository= new Mock<ILocalPurchaseRepository>();
controllerUnderTest = new HomeController(
uploadMockRepository.Object,
salesMockRepository.Object,
trsalesMockRepository.Object,
localMockRepository.Object);
}
#endregion
#region Unit Tests
//Add tests
#endregion
}
}

you could use a library like Moq to create mocks of the classes you need
a rough example of using Moq:
Declare the class you are mocking:
public Mock<IUploadRepository> UploadService { get; set; } = new Mock<IUploadRepository>();
Declare what should be returned when a particular method in your class is called.
UploadService.Setup(x => x.ClassMethodIWantToMock("Mock input param"))
.Returns(MyMockObject);
when instantiating your HomeController, you pass in the Mock classes you have created
moq quickstart wiki

Related

How to use WebApplicationFactory in .net6 (without speakable entry point)

In ASP.NET Core 6 default template moves everything from Sturtup.cs into Program.cs, and uses top-level statements in Program.cs, so there's no more (speakable) Program class ether.
That looks awesome, but now, I need to test all of this. WebApplicationFactory<T> still expects me to pass entry-point-class, but I cannot do this (due to it's name now being unspeakable).
How integration tests are expected to be configured in ASP.NET Core 6?
Note that if you are trying to use xUnit and its IClassFixture<T> pattern, you will run into problems if you just use the InternalsVisibleTo approach. Specifically, you'll get something like this:
"Inconsistent accessibility: base class WebApplicationFactory<Program> is less accessible than class CustomWebApplicationFactory."
Of course you can solve this by making CustomWebApplicationFactory internal but it only moves the problem as now your unit test class will give the same error. When you try to change it there, you will find that xUnit requires that tests have a public constructor (not an internal one) and you'll be blocked.
The solution that avoids all of this and allows you to still use IClassFixture<Program> is to make the Program class public. You can obviously do this by getting rid of the magic no class version of Program.cs, but if you don't want to completely change that file you can just add this line:
public partial class Program { } // so you can reference it from tests
Of course once it's public you can use it from your test project and everything works.
As an aside, the reason why you typically want to prefer using IClassFixture is that it allows you to set up your WebApplicationFactory just once in the test class constructor, and grab an HttpClient instance from it that you can store as a field. This allows all of your tests to be shorter since they only need to reference the client instance, not the factory.
Example:
public class HomePage_Get : IClassFixture<CustomWebApplicationFactory>
{
private readonly HttpClient _client = new HttpClient();
public HomePage_Get(CustomWebApplicationFactory factory)
{
_client = factory.CreateClient();
}
[Fact]
public async Task IncludesWelcome()
{
HttpResponseMessage response = await _client.GetAsync("/");
response.EnsureSuccessStatusCode();
string stringResponse = await response.Content.ReadAsStringAsync();
Assert.Contains("Welcome.", stringResponse);
}
}
Finally note that Damian Edwards' MinimalAPIPlayground was updated to use this approach after we discussed the issue. See this commit
The problem is was solved on ASP.NET Core RC1, but as of now (September 20, 2021) the docs are incomplete.
The compiler generates a Program class behind the scenes that can be used with WebApplicationFactory<>. The class isn't public though so the InternalsVisibleTo project setting should be used.
Damien Edwards' Minimal API sample uses the latest nightly bits. The test web app class is declared as :
internal class PlaygroundApplication : WebApplicationFactory<Program>
{
private readonly string _environment;
public PlaygroundApplication(string environment = "Development")
{
_environment = environment;
}
protected override IHost CreateHost(IHostBuilder builder)
{
...
In the application project file,InternalsVisibleTo is used to make the Program class visible to the test project:
<ItemGroup>
<InternalsVisibleTo Include="MinimalApiPlayground.Tests" />
</ItemGroup>
RC1 is feature complete and, judging by previous major versions, it will probably be the first version to have a Go Live license, which means it's supported in production.
I tried
<InternalsVisibleTo Include="MinimalApiPlayground.Tests" />
but no cigar! Removed it and added a partial class to program.cs
#pragma warning disable CA1050 // Declare types in namespaces
public partial class Program
{
}
#pragma warning restore CA1050 // Declare types in namespaces
amazingly it worked.

Autofac Register closed types and retrieve them at run time

I have an Interface that will take in a generic type T
internal interface IQuestion<T> where T : IWithOptionsId
{
Task<T> Provide(Guid id);
}
Following by that I will implement this interface in multiple classes. For example
public class SomeProvider : IQuestion<OptionsClass>
{
private readonly IRepository _repository;
public SomeProvider(IRepository repository)
{
_repository = repository;
}
public async Task<OptionsClass> Provide(Guid id)
...
}
To register this with outofac I used this
Autofac.RegisterAssemblyTypes(
Assembly.GetExecutingAssembly())
.AsImplementedInterfaces()
.AsClosedTypesOf(typeof(IQuestion<>));
My question is this. I have multiple instances for this interface. How do I access different instance once at the run time? If my IQuestion<T> will take in Options class and also it will take in Answer class how can I get an instance of those classes during run time?
I'm pretty sure you can just inject the instance itself. Not great practice, but it should work:
public SomeClass(SomeProvider<OptionsClass> provider)
You could also try creating a named instance when you register it, and inject that. See this and this.

Inject DbContext in Asp.Net Core. Concrete type or interface?

On an Asp.Net Core project I am injecting Entity Framework DbContext:
public MessageRepository(MyDbContext context) {
}
And the configuration is:
services
.AddEntityFramework()
.AddSqlServer()
.AddDbContext<Context>(x => x.UseSqlServer(connectionString);
Should I create an interface, IMyDbContext, and injecting it instead?
public class MyDbContext : DbContext, IMyDbContext { }
public MessageRepository(IMyDbContext context) {
}
In all ASP.NET Core examples I see the concrete type, MyDbContext, is being injected and not an interface ...
What option should I choose?
Currently working on a project myself, where I decided to go with 2 interfaces like this
public interface IDbContext : IDisposable
{
DbContext Instance { get; }
}
and
public interface IApplicationDbContext : IDbContext
{
DbSet<MyEntity> MyEntities { get; set; }
...
}
My concrete DbContext would then just implement the application context interface
public class ApplicationDbContext : DbContext, IApplicationDbContext
{
public DbContext Instance => this
public DbSet<MyEntity> MyEntities { get; set; }
}
This allows my implementation of the Application context to be injected as the application context interface, while also providing me access to the DbContext methods through the Instance property getter without having to add methods needed from the DbContext class to the interface.
Until now, this works great.
We're always injecting an interface, since it's easier to mock in unit and integration tests.
Are you willing to change the signature of the MessageRepository constructor? It relies on the concrete type.
Do you write tests for your code? Using and interface would make it easier to mock the database context.
If you've answered "no" to one or more of the above, inject the concrete type; otherwise, inject the interface.
[EDIT]
use the following.
context services.AddScoped<IApplicationDbContext>(provider => provider.GetService<ApplicationDbContext>());
In my opinion, you should always rely on an interface as #Uli said, but when it comes to the DbContext you need to take in mind that you are exposing all methods of the DbContext of EntityFramework Core
public class MyDbContext : DbContext, IMyDbContext { }
in that case, you don't need to implement any method that you are exposing because DbContext handles that for you.
BUT if EF code change the DbContext and you make an update to your project then you will be on a painful situation of updating your IMyDbContext every time, also all your unit testing. In my opinion, that will give you a lot of headaches.
This answers/questions can help you to understand why https://stackoverflow.com/a/6768712/819153
Unit testing EF - how to extract EF code out from BL?

Using Ninject with mocks in F#

This question is part of larger question that can be found here
As in out production code we use Ninject and constructor injection our services tend to look like this
public class Service : IService
{
private readonly IRepository _repository;
public Service(IRepository repository)
{
_repository = repository;
}
public Task<IEnumerable<SelectOption>> GetAlLogicOptions()
{
return _repository.GetOptionsAsync();
}
}
how ever list of constructor parameters may and will change over time. This is the reason that we want to have IoC to also be used in tests.
In C# NUnit this is quite easy as we have Ninject.MockingKernel that always provides mock implementation and in each test fixture we just rebind sut to it real implementation.
How to achieve same thing in F# xUnit.

wicket and AtUnit

I've started playing with Wicket and I've chosen Guice as dependency injection framework. Now I'm trying to learn how to write a unit test for a WebPage object.
I googled a bit and I've found this post but it mentioned AtUnit so I decided to give it a try.
My WebPage class looks like this
public class MyWebPage extends WebPage
{
#Inject MyService service;
public MyWebPage()
{
//here I build my components and use injected object.
service.get(id);
....
}
}
I created mock to replace any production MyServiceImpl with it and I guess that Guice in hand with AtUnit should inject it.
Now the problems are:
AtUnit expects that I mark target object with #Unit - that is all right as I can pass already created object to WicketTester
#Unit MyWebPage page = new MyWebPage();
wicketTester.startPage(page);
but usually I would call startPage with class name.
I think AtUnit expects as well that a target object is market with #Inject so AtUnit can create and manage it - but I get an org.apache.wicket.WicketRuntimeException: There is no application attached to current thread main. Can I instruct AtUnit to use application from wicketTester?
Because I don't use #Inject at MyWebPage (I think) all object that should be injected by Guice are null (in my example the service reference is null)
I really can't find anything about AtUnit inside Wicket environment. Am I doing something wrong, am I missing something?
I don't know AtUnit but I use wicket with guice and TestNG. I imagine that AtUnit should work the same way. The important point is the creation of the web application with the use of guice.
Here how I bind all this stuff together for my tests.
I have an abstract base class for all my tests:
public abstract class TesterWicket<T extends Component> {
#BeforeClass
public void buildMockedTester() {
System.out.println("TesterWww.buildMockedTester");
injector = Guice.createInjector(buildModules());
CoachWebApplicationFactory instance =
injector.getInstance(CoachWebApplicationFactory.class);
WebApplication application = instance.buildWebApplication();
tester = new WicketTester(application);
}
protected abstract List<Module> buildModules();
The initialization is done for every test class. The subclass defines the necessary modules for the test in the buildModules method.
In my IWebApplicationFactory I add the GuiceComponentInjector. That way, after all component instantiation, the fields annotated with #Inject are filled by Guice:
public class CoachWebApplicationFactory implements IWebApplicationFactory {
private static Logger LOG = LoggerFactory.getLogger(CoachWebApplicationFactory.class);
private final Injector injector;
#Inject
public CoachWebApplicationFactory(Injector injector) {
this.injector = injector;
}
public WebApplication createApplication(WicketFilter filter) {
WebApplication app = injector.getInstance(WebApplication.class);
Application.set(app);
app.addComponentInstantiationListener(new GuiceComponentInjector(app, injector));
return app;
}
}