How to do Unit Test with Dependency Injection .net Core 2 - unit-testing

I start to develop a new web application, I create a Domain Object, Inteface, DAL and BLL...
I would like to test all before use that.
If I use the developed function in web application in .net core 2 I put in Startup.cs some code like this :
public void ConfigureServices(IServiceCollection services)
{
**services.AddTransient<ITableOfTableRepository, DBTableOfTableRepository>();**
services.AddMvc();
services.AddSingleton<IConfiguration>(Configuration);
}
And in my Controller add this code
public class TablesController : Controller
{
private readonly ITableOfTableRepository _repository;
public TablesController(ITableOfTableRepository repository)
{
this._repository = repository;
}
How to do a UnitTest project for testing all before of the use in web application?
How to use dependency Injection in unit test?
BR

If you are trying to develop in a test first approach...
You will pass by several steps:
Your test is not compiling because you need to write a controller action and create an interface
Once you created an interface you could mock/stub it (using framework like NSubstitute or others) and inject when you create the controller
var userService = Substitute.For();
...
var controller = new MyController(userService)
you write the controller code for your test to pass

Related

How to test method in XUnit that needs UserManager, but uses in-memory database

I'm using ASP.NET Core 3.1 and XUnit for my unit tests.
I built a database context factory class that instantiates an in-memory version of my database:
public static class DbContextFactory
{
public static ApplicationDbContext CreateDbContext()
{
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
var modelBuilder = new ModelBuilder(new ConventionSet());
var dbContext = new ApplicationDbContext(options);
var onModelCreatingMethod = dbContext.GetType().GetMethod("OnModelCreating",
BindingFlags.Instance | BindingFlags.NonPublic);
onModelCreatingMethod.Invoke(dbContext,
new object[] { modelBuilder });
return dbContext;
}
}
This is the current test class I'm trying to use:
public class AdminServiceTests
{
public ApplicationDbContext context { get; set; }
public IAdminService adminService { get; set; }
public AdminServiceTests()
{
this.context = DbContextFactory.CreateDbContext();
this.adminService = new AdminService(userManager, context);
}
[Fact]
public async Task DeleteUserShouldDeleteUser()
{
// What to do ???
}
}
In order for me to test my admin service, I need to provide a user manager. It should be linked with the database I currently have created.
How can I make that happen?
You're making a common mistake of testing the framework. All your test needs to do is ensure that AdminService.DeleteUser calls UserManager.DeleteAsync. Whether or not that spirals down into actually removing the user from the database is 1) not a concern of the service and 2) an implementation detail of both ASP.NET Core Identity and EF Core, both of which have their own extensive test suites to ensure that happens.
As such, you can just use a library like Moq to create a mock of UserManager<TUser> and then do something like:
userManagerMock.Verify(x => x.DeleteAsync(user), Times.Once());
It's worth mentioning here that this also serves to point out a bit of a flaw in this kind of design. You have a dependency on ASP.NET Core Identity whether or not you put an AdminService wrapper around that. Unless your service is doing something special outside of just proxying to UserManager here (e.g. coordinating multiple actions, like maybe deleting the user triggers a notification or something), then your service is pointless, and you should just use UserManager directly. Developers make this kind of mistake constantly; abstraction for the sake of abstraction only hurts your code. It adds additional maintenance concerns, testing concerns, and obscures what the code is actually doing.

ASP.NET Web API Unit Test Autofac Module with BuildManager.GetReferencedAssemblies()

Working on a project in ASP.NET Web API 2 which has Autofac as my IoC container. This project is hosted on IIS and in my Autofac module I use the following method to scan for assemblies:
var asm = BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToArray();
Why?
https://docs.autofac.org/en/latest/register/scanning.html#iis-hosted-web-applications
But now we are making Unit Tests using NUnit, during my setup I register my module which uses this method. Now I receive the following exception when running my tests:
System.InvalidOperationException: 'This method cannot be called during the application's pre-start initialization phase.'
I understand why I have this exception but I don't have a clue how to make my code work in tests and for deployment environments.
Setup method of NUnit:
[TestFixture]
public abstract class ApplicationTestBase
{
[SetUp]
public override void Init()
{
var builder = new ContainerBuilder();
// If the class requires auto mapper mapping, initialize them
// We do this in order not to init them for every test => optimalisation!
if (GetType().GetCustomAttributes<RequiresAutoMapperMappingsAttribute>(false) != null)
{
builder.RegisterModule<AutoMapperModule>();
}
this.Container = builder.Build();
}
}
Do I need to create a new module specific for my Unit tests or is there another way for this?
AutoMapperTest
[RequiresAutoMapperMappings]
[TestFixture]
public class AutoMapperTests : ApplicationTestBase
{
[Test]
public void Assert_Valid_Mappings()
{
Mapper.AssertConfigurationIsValid();
}
}
UPDATE
Like Cyril mentioned: Why do you need Ioc in your unit tests? I went searching and indeed you don't have to use the Ioc in your tests. So I ditched the Ioc and initialized my mapper configuration byy doing:
Mapper.Initialize(configuration =>
{
var asm = AppDomain.CurrentDomain.GetAssemblies()
.Where(a => a.FullName.StartsWith("ProjectWebService."));
configuration.AddProfiles(asm);
});
I would recommend separating the "how to load assemblies" logic from the "do assembly scanning and register modules logic."
Right now I'm guessing you have something like this all in one method.
public IContainer BuildContainer()
{
var asm = BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToArray();
var builder = new ContainerBuilder();
builder.RegisterAssemblyTypes(asm);
var container = builder.Build();
}
Not exactly that, but something similar - the loading of assemblies is inlined and directly used.
Separate that so you can swap that logic in for testing. For example, consider allowing a parameter to be optionally passed so you can override the logic in test.
public IContainer BuildContainer(Func<IEnumerable<Assembly>> assemblyLoader = null)
{
IEnumerable<Assembly> asm = null;
if (assemblyLoader != null)
{
asm = assemblyLoader();
}
else
{
asm = BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToArray();
}
var builder = new ContainerBuilder();
builder.RegisterAssemblyTypes(asm);
var container = builder.Build();
}
Your default logic will work the way you want, but then in testing you can swap in something else.
var container = BuildContainer(() => AppDomain.GetAssemblies());
There are lots of ways you can do that swap-in. It could be anything from a static property you can set somewhere to a virtual method you can override somewhere. The point is, by separating the assembly loading logic you can get the test-time behavior to work but still use the registration behavior you're after.

JUnit Test for Dao and Service with Arquillian

Hi I'm trying to test my Service and Dao layers for a Java EE 7 application.
So I looking for testing solutions follow tutorials using Arquillian with junit test and wildfly remote dependence.
Dao and Service interfaces with relative implementations have been created, following my junit test with Arquillian:
#RunWith(Arquillian.class)
public class GenericServiceTest {
#Inject
private EmployeeService employeeService;
#Deployment
public static JavaArchive createDeployment() {
return ShrinkWrap
.create(JavaArchive.class)
.addAsManifestResource("META-INF/persistence.xml",
"persistence.xml")
.addClasses(EmployeeDao.class, EmployeeDaoImpl.class,
EmployeeService.class, EmployeeServiceImpl.class,
Employee.class)
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
}
#Test
#Transactional
public void should_crud() {
// Gets all the objects
assertNotNull(employeeService);
Employee employee = employeeService.get(new Integer(1));
assertNotNull(employee);
}
}
Running class as JUnit Test it doesn't work with this error:
Caused by: java.lang.Exception: "WFLYCTL0216: Management resource '[(\"deployment\" => \"test.war\")]' not found"
Test pass if any classes has been added to ShrinkWrap as following:
#RunWith(Arquillian.class)
public class GenericDaoTest {
#Inject
private EmployeeService employeeService;
#Deployment
public static JavaArchive createTestableDeployment() {
final JavaArchive jar = ShrinkWrap.create(JavaArchive.class)
.addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml");
return jar;
}
#Test
public void should_crud() {
}
}
How can I create a working test using arquillian for Java EE 7 adding service class implementations?
And I have To add every Class and Intefaces that have to be called (for example all entities,dao etc classes) or only Service Interface and implementation Class?
Thanks a lot
Since you're developing a javaee application, I would suggest you to create a War archive instead of Jar.
You can add the whole package using
ShrinkWrap.addPackages(true, "com.yourpackage.name") so you don't have to add your classes independently.
If I understand the question correctly you want to test a war archive.
If this is the case you should change
return ShrinkWrap
.create(JavaArchive.class)
to
return ShrinkWrap
.create(WarArchive.class)
In addition you should add your persistence.xml file to the META-INF folder like:
.addAsResource("test-persistence.xml", "META-INF/persistence.xml")
If you want to use the annotation #Transactional in your tests, you need to add a few dependencies to your test scope. If you didn't add them yet you can read at http://arquillian.org/modules/transaction-extension/ what dependencies to add.

Unit testing with mvc api & ninject

Sorry if this comes across as a stupid question im just not sure how to get started writing some unit tests.
I have a solution containing an api and a unit test project. The api has a repository/interface used for data access using ninject.
My question is how is my best way to unit test my api controllers. I have read a little about Moq but not sure if I need to use it as I want to test against my database.
I have read that I need to use a [TestInitialize] attribute
[TestInitialize]
public void MyTestInitialize()
{
var kernel = NinjectWebCommon.CreatePublicKernel();
kernel.Bind<BusinessController>().ToSelf();
}
My problem is my test project cant resolve CreatePublicKernel
Checking the NinjectWebCommon class in the api there is no function called CreatePublicKernel.
What am I missing here?
Ninject (or other DI library) is used only to provide dependencies into your controller's constructor. E.g. if you need BusinessController which requires two repositories, then controller should have constructor which expects these dependencies:
public BusinessController(IUserRepository userRepository,
IOrderRepository orderRepository)
{
_userRepository = userRepository;
_orderRepository = orderRepository;
}
If you want to write unit tests for your controller, you should provide mocked implementations of these repositories. Use Moq or other framework for creating mocks:
var userRepositoryMock = new Mock<IUserRepository>();
var orderRepositoryMock = new Mock<IOrderRepository>();
// setup mocks here
var controller = new BusinessController(userRepositoryMock.Object,
orderRepositoryMock.Object);
If you are writing integration tests for your controller, you should provide real implementations of these repositories, which use some real database.
var userRepository = new NHibernateUserRepository();
var orderRepository = new NHibernateOrderRepository();
// prepare some data in database here
var controller = new BusinessController(userRepository, orderRepository);
You can move controller instantiation into some method which is executed before each test (SetUp or TestInitialize method) in order to remove code duplication from your tests.
UPDATE: You also can use Ninject for integration testing. Just create Ninject module which will be used both by your real application and integration tests:
public class FooModule : NinjectModule
{
public override void Load()
{
Bind<IUserRepository>().To<NHibernateUserRepository>();
Bind<IOrderRepository>().To<NHibernateOrderRepository>();
Bind<BusinessController>().ToSelf();
}
}
Then use this module both to create kernel in NinjectWebCommon.CreateKernel method and kernel in your tests:
var kernel = new StandardKernel(new FooModule());
var controller = kernel.Get<ValuesController>();

How to test GWT/GWTP project?

I am currently building a web application using GWT, GWTP.
And I have some questions about testings:
Is there a Lint-like tool for GWTP or GWT?
How to test presenters? (GWTP with Mockito)
How to test views?
Thanks.
Presenters can be easily unit-tested using Jukito. Here's a quick example of a Presenter being tested using Jukito.
#RunWith(JukitoRunner.class)
public class ShowCommentsPresenterTest {
#Inject
private ShowCommentsPresenter showCommentsPresenter;
#Inject
private PlaceManager placeManager;
#Test
public void onReset_PlaceRequestHasNoShowId_ShouldHideView() {
//given
when(placeManager.getCurrentPlaceRequest()).thenReturn(new PlaceRequest());
//when
showCommentsPresenter.onReset();
//then
verify(showCommentsPresenter.getView()).hide();
}
#Test
public void onReset_PlaceRequestHasAShowId_ShouldDisplayView() {
//given
String someShowId = "12345";
when(placeManager.getCurrentPlaceRequest()).thenReturn(new PlaceRequest()
.with(ParameterTokens.getShowId(), someShowId));
//when
showCommentsPresenter.onReset();
//then
verify(showCommentsPresenter.getView()).display();
}
}
In GWTP's philosophy, Views should not be unit-tested directly. Using a dumb View that is a slave to the Presenter, most of the logic can be tested through unit tests on the Presenters. Tools like Selenium are a better fit for testing UI interactivity.
Google put out a great article about using different testing methodologies with GWT. Definitely check it out. Personally, I use JUnit when I'm testing back-end stuff like business logic, and Selenium for testing the UI and application as a whole from the browser's perspective.