I am trying to create a unit test that uses EclipseLink via JPA and I noticed that I needed to inject a DAO into a listener. The code itself works as expected inside a container, but I am having trouble making a unit test for it.
The listener looks like this.
#ApplicationScoped
public class ParticipantListener {
#Inject
private ParticipantDAO dao;
#PrePersist
#PreUpdate
void ensureNoDuplicateSin(final Participant e) throws DuplicateSinException {
final Participant bySin = dao.getBySinAndNotSelf(e.getSin(), e);
if (bySin != null && bySin.getId() != e.getId()) {
throw new DuplicateSinException();
}
}
}
When I run in a unit test dao is not injected.
My test is initialized as follows:
weld = new Weld();
final WeldContainer container = weld.initialize();
vf = Validation.buildDefaultValidatorFactory();
final Map<String, String> props = new HashMap<>();
props.put("javax.persistence.provider", "org.eclipse.persistence.jpa.PersistenceProvider");
emf = Persistence.createEntityManagerFactory("test-pu", props);
em = emf.createEntityManager();
which obviously should not work because there's no relationship between the em/emf and the container
I needed to set the javax.persistence.bean.manager to point to Weld's bean manager. In addition I found that I also
weld = new Weld();
final WeldContainer container = weld.initialize();
final JpaProvider jpaProvider = container.select(JpaProvider.class).get();
final Map<String, Object> props = new HashMap<>();
props.put("javax.persistence.provider", "org.eclipse.persistence.jpa.PersistenceProvider");
props.put("javax.persistence.bean.manager", container.getBeanManager());
emf = Persistence.createEntityManagerFactory("test-pu", props);
em = emf.createEntityManager();
jpaProvider.setEntityManager(em);
In addition I had to change the DAO to not use #PersistenceContext and use #Inject for the entity manager and create a JpaProvider class. During the test it will set the entity manager from the container instance.
#ApplicationScoped
public class JpaProvider {
private EntityManager em;
#Produces
public EntityManager getEntityManager() {
return em;
}
#PersistenceContext
public void setEntityManager(final EntityManager em) {
this.em = em;
}
}
Your solution sounds unwieldy and as far as I understand you needed to change the code under test (which is not-a-good-thing-to-do (TM)).
Rather have a look into arquillian (http://arquillian.org/) and the use with mockito.
Here's a little bit of boilerplate code showing how I usually do this:
#RunWith(Arquillian.class)
public class TestParticipantListener {
// Collection of producer methods and/or static producer fields
// that mock the injected dependencies for the class under test
public static class LocalMocks {
#Produces ParticipantDAO getParticipantDAO() {
ParticipantDAO participantDAO = Mockito.mock(...);
return participantDAO
}
}
#Deployment
public static WebArchive createDeployment() {
PomEquippedResolveStage pom = Maven.resolver().loadPomFromFile("pom.xml");
BeansDescriptor beansXml = Descriptors.create(BeansDescriptor.class)
.addDefaultNamespaces().getOrCreateAlternatives()
.up();
WebArchive jar = ShrinkWrap.create(WebArchive.class)
.addAsLibraries(pom.resolve("org.mockito:mockito-core").withTransitivity().asFile())
.addClass(ParticipantListener.class)
.addClass(ParticipantDAO.class)
.addClass(TestParticipantListener.LocalMocks.class)
// ... other dependencies
.addAsWebInfResource(new StringAsset(beansXml.exportAsString()), "beans.xml");
return jar;
}
#Inject ParticipantListener participantListenerUnderTest;
#Test
public void test() {
... whatever your test is, using the injected instance
}
}
Related
In my Asp.net Core 2.0 application, I am trying to unit test my data service layer (.Net Standard Class Library) that uses the Microsoft.Extensions.Configuration.IConfiguration dependency injection.
I am using XUnit and don't know how to pass IConfiguration from my unit test class. I tried the following implementation and getting the error
Message: The following constructor parameters did not have matching fixture data: IConfiguration configuration.
I am really new to the testing frameworks and don't even know if dependency injection can be used as I am trying to do in my code snippet.
My Unit test class is as follow
public class SqlRestaurantDataCLUnitTest
{
private readonly IConfiguration configuration;
public SqlRestaurantDataCLUnitTest(IConfiguration configuration)
{
this.configuration = configuration;
}
[Fact]
public void AddTest()
{
var restaurantDataCL = new SqlRestaurantDataCL(configuration);
var restaurant = new Restaurant
{
Name = "TestName",
Cuisine = CuisineType.None
};
var result = restaurantDataCL.Add(restaurant);
Assert.IsNotType(null, result.Id);
}
}
My data service layer is as follow
public class SqlRestaurantDataCL : IRestaurantDataCL
{
private readonly IConfiguration configuration;
public SqlRestaurantDataCL(IConfiguration configuration)
{
this.configuration = configuration;
}
public Restaurant Add(Restaurant restaurant)
{
using (var db = GetConnection())
{
string insertSql = #"INSERT INTO [dbo].[RESTAURANTS]([Cuisine], [Name])
OUTPUT INSERTED.*
VALUES (#Cuisine, #Name)";
restaurant = db.QuerySingle<Restaurant>(insertSql, new
{
Cuisine = restaurant.Cuisine,
Name = restaurant.Name
});
return restaurant;
}
}
private IDbConnection GetConnection()
{
return new SqlConnection(configuration.GetSection(Connection.Name).Value.ToString());
}
}
public class Connection
{
public static string Name
{
get { return "ConnectionStrings: OdeToFood"; }
}
}
Unit tests have a very useful habit of exposing design issues. In this case you have made some design choices that prove difficult to test because of tight coupling to framework concerns as well as static concerns.
First, it looks like SqlRestaurantDataCL actually depends on a connection factory
public interface IDbConnectionFactory {
IDbConnection GetConnection();
}
Which would refactor the data implementation as advised to depend on that abstraction.
public class SqlRestaurantDataCL : IRestaurantDataCL {
private readonly IDbConnectionFactory factory;
public SqlRestaurantDataCL(IDbConnectionFactory factory) {
this.factory = factory;
}
public Restaurant Add(Restaurant restaurant) {
using (var connection = factory.GetConnection()) {
string insertSql = #"INSERT INTO [dbo].[RESTAURANTS]([Cuisine], [Name])
OUTPUT INSERTED.*
VALUES (#Cuisine, #Name)";
restaurant = connection.QuerySingle<Restaurant>(insertSql, new {
Cuisine = restaurant.Cuisine,
Name = restaurant.Name
});
return restaurant;
}
}
//...
}
The assumption is that Dapper is being used to make the query above.
With the introduction of the abstracted dependencies, they can be mocked as needed when testing in isolation.
public class SqlRestaurantDataCLUnitTest {
[Fact]
public void AddTest() {
//Arrange
var connection = new Mock<IDbConnection>();
var factory = new Mock<IDbConnectionFactory>();
factory.Setup(_ => _.GetConnection()).Returns(connection.Object);
//...setup the connection to behave as expected
var restaurantDataCL = new SqlRestaurantDataCL(factory.Object);
var restaurant = new Restaurant {
Name = "TestName",
Cuisine = CuisineType.None
};
//Act
var result = restaurantDataCL.Add(restaurant);
//Assert
Assert.IsNotType(null, result.Id);
}
}
Now if you meant to actually touch the real database then this is not an isolation unit test but instead an integration test, that will have a different approach.
In production code, the factory can be implemented
public class SqlDbConnectionFactory : IDbConnectionFactory {
private readonly ConnectionSetings connectionSettings;
SqlDbConnectionFactory(ConnectionSetings connectionSettings) {
this.connectionSettings = connectionSettings;
}
public IDbConnection GetConnection() {
return new SqlConnection(connectionSettings.Name));
}
}
Where ConnectionSetings is defined as a simple POCO to store the connection string
public class ConnectionSetings {
public string Name { get; set; }
}
In the composition root the settings can be extracted from configurations
IConfiguration Configuration; //this would have been set previously
public void ConfigureServices(IServiceCollection services) {
//...
var settings = Configuration
.GetSection("ConnectionStrings:OdeToFood")
.Get<ConnectionSetings>();
//...verify settings (if needed)
services.AddSingleton(settings);
services.AddSingleton<IDbConnectionFactory,SqlDbConnectionFactory>();
services.AddSingleton<IRestaurantDataCL,SqlRestaurantDataCL>();
//Note: while singleton was used above, You can decide to use another scope
// if so desired.
}
There was really no need to be passing IConfiguration around as it is more of a framework concern that is really only relevant at start up.
The Setup: I've registered a configuration service that pulls data from appsettings.json and it works fine. I also have a controller that uses that service to get settings from that file, again this works like it's supposed to:
public class ApiController : Controller
{
private readonly string _apiUri;
public ApiController(IOptions<Configurator> config)
{
_apiUri = config.Value.ApiSettings.ApiBaseUrl +
config.Value.ApiSettings.ApiVersion;
}
//...
}
Now note, I'm new to automated unit testing and to asp.net core. What I'd like to do is to decouple the ApiController's reliance on the injected service so that I can use a separate XUnit test project to test functions inside the controller, similar to the example in this tutorial.
To do this I created a model and interface representing the ApiSettings section of my appsettings.json file:
"ApiSettings": {
"ApiBaseUrl": "https://example.com/api/",
"ApiVersion": "v1/"
}
The Model:
public class ApiSettings : IApiSettings
{
public string ApiBaseUri { get; set; }
public string ApiVersion { get; set; }
}
The Interface:
public interface IApiSettings
{
string ApiBaseUri { get; set; }
string ApiVersion { get; set; }
}
I then created a class that would be dependent on the service to inject the settings:
public class ApiSettingsBuilder
{
private readonly string _apiUri;
public ApiSettingsBuilder(IOptions<Configurator> config)
{
_apiUri = config.Value.ApiSettings.ApiBaseUrl +
config.Value.ApiSettings.ApiVersion;
}
public string ApiUri { get { return _apiUri; } }
}
The Problem: How do I create an new instance of this class?
public class ApiController : Controller
{
private readonly string _apiUri;
public ApiController()
{
ApiSettingsBuilder builder = new ApiSettingsBuilder(/*What do I do here*/);
_apiUri = builder.ApiUri;
}
public ApiController(IApiSettings settings)
{
//For testing
_apiUri = settings.ApiBaseUrl + settings.ApiVersion;
}
//...
}
Also, I know this is all a bit overkill, but I would still like an answer because It would possibly be useful in other scenarios.
You don't have to create new classes for unit testing purposes, you can mock the interface of your IOptions using appropriate framework, e.g. Moq:
var configurator = new Configurator() { ApiBaseUrl = "abc" };
var mock = new Mock<IOptions<Configurator>>();
mock.Setup(ap => ap.Value).Returns(configurator);
Then you can pass mocked object to your constructor for unit testing:
var controller = new ApiController(mock.Object);
i have a service method that get session attribute and i want to make unit test for this service method and i was wondering how to mock the HttpSession in jsf.
1- use the FacesContextMocker class:
public abstract class FacesContextMocker extends FacesContext {
private FacesContextMocker() {}
private static final Release RELEASE = new Release();
private static class Release implements Answer<Void> {
#Override
public Void answer(InvocationOnMock invocation) throws Throwable {
setCurrentInstance(null);
return null;
}
}
public static FacesContext mockFacesContext() {
FacesContext context = Mockito.mock(FacesContext.class);
setCurrentInstance(context);
Mockito.doAnswer(RELEASE).when(context).release();
return context;
}
}
2- in the test class #Before method do the following:
FacesContextMocker.mockFacesContext();
ExternalContext externalContext = Mockito.mock(ExternalContext.class);
Mockito.when(FacesContext.getCurrentInstance().getExternalContext())
.thenReturn(externalContext);
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(
FacesContext.getCurrentInstance().getExternalContext()
.getRequest()).thenReturn(request);
HttpSession httpSession = Mockito.mock(HttpSession.class);
Mockito.when(GeneralUtils.getHttpSession()).thenReturn(httpSession);
3- the getHttpSession method is as follows:
public static HttpSession getHttpSession() {
return ((HttpServletRequest) FacesContext.getCurrentInstance()
.getExternalContext().getRequest()).getSession();
}
4- in the test method do the following:
Mockito.when(
GeneralUtils.getHttpSession().getAttribute(
"userID")).thenReturn("1");
5- this is assuming that in your service method that you are making the unit test for you have code like:
String currentUserID = (String) GeneralUtils.getHttpSession()
.getAttribute(userID);
I have been given the task to evaluate codeFirst and possible to use for all our future projects.
The evaluation is based on using codeFirst with an existing database.
Wondering if it's possible to mock the repository using codeFirst 4.1.(no fakes)
The idea is to inject a repository into a service and moq the repository.
I have been looking on the net but I have only found an example using fakes.I dont want to use fakes I want to use moq.
I think my problem is in the architecture of the DAL.(I would like to use unitOfWork etc.. by I need to show a working moq example)
Below is my attempt(Failed miserably) due to lack of knowledge on Code first 4.1.
I have also uploaded a solution just in case somebody is in good mood and would like to change it.
http://cid-9db5ae91a2948485.office.live.com/browse.aspx/Public%20Folder?uc=1
I am open to suggestions and total modification to my Dal.Ideally using Unity etc.. but I will worry about later.
Most importantly I need to be able to mock it. Without ability to use MOQ we will bin the project using EF 4.1
Failed attempt
//CodeFirst.Tests Project
[TestClass]
public class StudentTests
{
[TestMethod]
public void Should_be_able_to_verify_that_get_all_has_been_called()
{
//todo redo test once i can make a simple one work
//Arrange
var repository = new Mock<IStudentRepository>();
var expectedStudents = new List<Student>();
repository.Setup(x => x.GetAll()).Returns(expectedStudents);
//act
var studentService = new StudentService(repository.Object);
studentService.GetAll();
//assert
repository.Verify(x => x.GetAll(), Times.AtLeastOnce());
}
}
//CodeFirst.Common Project
public class Student
{
public int StudentId { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
}
public interface IStudentService
{
IEnumerable<Student> GetAll();
}
//CodeFirst.Service Project
public class StudentService:IStudentService
{
private IStudentRepository _studentRepository;
public StudentService()
{
}
public StudentService(IStudentRepository studentRepository)
{
_studentRepository = studentRepository;
}
public IEnumerable<Student> GetAll()
{
//TODO when mocking using moq this will actually call the db as we need a separate class.
using (var ctx = new SchoolContext("SchoolDB"))
{
_studentRepository = new StudentRepository(ctx);
var students = _studentRepository.GetAll().ToList();
return students;
}
}
}
//CodeFirst.Dal Project
public interface IRepository<T> where T : class
{
T GetOne(Expression<Func<T, bool>> predicate);
IEnumerable<T> GetAll();
IEnumerable<T> Find(Expression<Func<T, bool>> predicate);
void Add(T entity);
void Delete(T entity);
T Single(Func<T, bool> predicate);
T First(Func<T, bool> predicate);
}
public class RepositoryBase<T> : IRepository<T> where T : class
{
private readonly IDbSet<T> _dbSet;
public RepositoryBase(DbContext dbContext)
{
_dbSet = dbContext.Set<T>();
if (_dbSet == null) throw new InvalidOperationException("Cannot create dbSet ");
}
protected virtual IDbSet<T> Query
{
get { return _dbSet; }
}
public T GetOne(Expression<Func<T, bool>> predicate)
{
return Query.Where(predicate).FirstOrDefault();
}
public IEnumerable<T> GetAll()
{
return Query.ToArray();
}
public IEnumerable<T> Find(Expression<Func<T, bool>> predicate)
{
return Query.Where(predicate).ToArray();
}
public void Add(T entity)
{
_dbSet.Add(entity);
}
public void Delete(T entity)
{
_dbSet.Remove(entity);
}
public T Single(Func<T, bool> predicate)
{
return Query.Where(predicate).SingleOrDefault();
}
public T First(Func<T, bool> predicate)
{
return Query.Where(predicate).FirstOrDefault();
}
}
public class SchoolContext:DbContext
{
public SchoolContext(string connectionString):base(connectionString)
{
Database.SetInitializer<SchoolContext>(null);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Not sure why I have to do this.Without this when using integration testing
//as opposed to UnitTests it does not work.
modelBuilder.Entity<Student>().ToTable("Student"); }
public DbSet<Student> Students { get; set; }
}
public interface IStudentRepository:IRepository<Student>
{
}
public class StudentRepository : RepositoryBase<Student>, IStudentRepository
{
public StudentRepository(DbContext dbContext)
: base(dbContext)
{
}
public IEnumerable<Student> GetStudents()
{
return GetAll();
}
}
Again feel free to modify or whatever is needed to help me to get something together.
Thanks a lot for your help
When I started with repository and unit of work patterns I used the implementation similar to this (it is for ObjectContext API but converting it to DbContext API is simple). We used that implementation with MOQ and Unity without any problems. By the time implementations of repository and unit of work have evolve as well as the approach of injecting. Later on we found that whole this approach has serious pitfalls but that was alredy discussed in other questions I referenced here (I highly recommend you to go through these links).
It is very surprising that you are evaluating the EFv4.1 with high emphasis on mocking and unit testing and in the same time you defined service method which is not unit-testable (with mocking) at all. The main problem of you service method is that you are not passing repository/context as dependency and because of that you can't mock it. The only way to test your service and don't use the real repository is using some very advanced approach = replacing mocking and MOQ with detouring (for example Moles framework).
First what you must do is replacing your service code with:
public class StudentService : IStudentService
{
private readonly IStudentRepository _studentRepository;
public StudentService(IStudentRepository studentRepository)
{
_studentRepository = studentRepository;
}
public IEnumerable<Student> GetAll()
{
return _studentRepository.GetAll().ToList();
}
}
Btw. this is absolutely useless code and example of silly layering which doesn't offer any useful functionality. Just wrapping the call to repository only shows that service is not needed at all as well as unit testing this method is not needed. The main point here is integration test for GetAll method.
Anyway if you want to unit thest such method with MOQ you will do:
[TestClass]
public class StudentsServiveTest
{
private Mock<IRespository<Student>> _repo;
[TestInitialize]
public void Init()
{
_repo = new Mock<IRepository<Student>>();
_repo.Setup(r => r.GetAll()).Returns(() => new Student[]
{
new Student { StudentId = 1, Name = "A", Surname = "B" },
new Student { StudentId = 2, Name = "B", Surname = "C" }
});
}
[TestMethod]
public void ShouldReturnAllStudents()
{
var service = new StudentsService(_repo.Object);
var data = service.GetAll();
_repo.Verify(r => r.GetAll(), Times.Once());
Assert.IsNotNull(data);
Assert.AreEqual(2, data.Count);
}
}
The issue from what I can see is that you are throwing away the mock object and newing up a new instance
_studentRepository = new StudentRepository(ctx);
Perhaps add a method on the interface to add the context object and reuse the same instance that was injected in the constructor.
using (var ctx = new SchoolContext("SchoolDB"))
{
_studentRepository.Context = ctx;
var students = _studentRepository.GetAll().ToList();
return students;
}
}
I need to write a test layer to Test my WCF RIA Domain Service layer which is build on top of Entity Framework context. I have come across some patterns which suggest to use a repository and then use the Domain Service factory to intilize the domain service with a repository instance to use. One of the sample which fits the requirement is explained here on Vijay's blog(http://blogs.msdn.com/vijayu/archive/2009/06/08/unit-testing-business-logic-in-net-ria-services.aspx). The problem with this implementation is that it initilize the repository only for a specific Domain Object e.g. Customer/Product but it provides no way to create a repository which can return any object which i would like to return.
Please suggest what is the right way of doing this and whether it is possible or not.
Thanks in advance,
Manoj
I got around this issue by extending the sample with a RepositoryCollection object, which automatically instantiates LinqToSqlRepositories as needed, and also allows the insertion of mock/stub repositories manually for unit testing.
public class RepositoryCollection : IDisposable
{
private Dictionary<Type, object> _repositories = new Dictionary<Type, object>();
private DataContext _context;
public RepositoryCollection() { }
public RepositoryCollection(DataContext context)
{
_context = context;
}
public IRepository<T> Get<T>() where T : class
{
if(!_repositories.ContainsKey(typeof(T)))
_repositories.Add(typeof(T), new LinqToSqlRepository<T>(_context));
return _repositories[typeof(T)] as IRepository<T>;
}
public RepositoryCollection Insert<T>(IRepository<T> repository) where T : class
{
_repositories[typeof(T)] = repository;
return this;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public void SubmitChanges()
{
if (_context != null)
_context.SubmitChanges();
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if(_context != null)
_context.Dispose();
}
}
}
Then, in your domain service, you use it like so:
private RepositoryCollection _repositoryCollection;
public MyDomainService(RepositoryCollection repositoryCollection = null)
{
_repositoryCollection = repositoryCollection ?? new RepositoryCollection(new MyDataContext());
}
public IQueryable<Customer> GetCustomers()
{
return _repositoryCollection.Get<Customer>().Query();
}
public IQueryable<Product> GetProducts()
{
return _repositoryCollection.Get<Product>().Query();
}
.. other methods go here ...