doctrine 2 - working with repositories - doctrine-orm

I would like to start using Doctrine 2 for a new project but I noticed that doctrine now allows to define repositories: http://mackstar.com/blog/2010/10/04/using-repositories-doctrine-2
I'm not sure how to structure my project now because isn't one of the purposes of using repositories that you can switch to another ORM when needed.
So if you use Doctrine repositories, this possibility is gone.
Or should I define my own repositories and in those repositories make use of calls to the doctrine repository? That seems a bit odd...

Just to follow up on the comments, this is the base repository class that I use.
namespace Cerad\Bundle\CoreBundle\Doctrine;
use Doctrine\ORM\EntityRepository as BaseRepository;
class EntityRepository extends BaseRepository implements ApplicationRepository
{
// Create main entity
public function createEntity($params = array())
{
$entityName = $this->getEntityName();
return new $entityName($params);
}
// Allow null for id
public function find($id)
{
return $id ? parent::find($id) : null;
}
/* ==========================================================
* Persistence
*/
public function persist($entity) { return $this->getEntityManager()->persist($entity); }
public function remove($entity) { return $this->getEntityManager()->remove($entity); }
public function flush() { return $this->getEntityManager()->flush(); }
public function clear() { return $this->getEntityManager()->clear(); }
}
Having the ability to support multiple repository types is actually quite useful. I'll often implement InMemory repositories which work off of yaml files for initial development and testing.

Related

How to unit test a service call in xUnit and nSubstitute

I been trying to figure out how i can unit test service and so far have got nowhere.
I am using xUnit and NSubstitute (as advised by friends), below is the simple test that i want to run (which fails currently).
public class UnitTest1
{
private readonly RallyService _rallyService;
public UnitTest1(RallyService rallyService)
{
_rallyService= rallyService;
}
[Fact]
public void Test1()
{
var result = _rallyService.GetAllRallies();
Assert.Equal(2, result.Count());
}
}
My rally service class makes a simple call to the db to get all Rally entites and returns those:
public class RallyService : IRallyService
{
private readonly RallyDbContext _context;
public RallyService(RallyDbContext context)
{
_context = context;
}
public IEnumerable<Rally> GetAllRallies()
{
return _context.Rallies;
}
}
Any guidance would be appreciated.
Since you use .NET Core, I assume you also use Entity Framework Core. While it was possible to mock most of the operations in the previous EF version, however the EF Core suggests to use in-memory database for unit testing. I.e. you don't need to mock RallyDbContext, hence NSubstitute is not needed for this particular test. You would need NSubstitute to mock the service when testing a controller or application using the service.
Below is your Test1 written using in-memory database.
public class UnitTest1
{
private readonly DbContextOptions<RallyDbContext> _options;
public UnitTest1()
{
// Use GUID for in-memory DB names to prevent any possible name conflicts
_options = new DbContextOptionsBuilder<RallyDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
}
[Fact]
public async Task Test1()
{
using (var context = new RallyDbContext(_options))
{
//Given 2 records in database
await context.AddRangeAsync(new Rally { Name = "rally1" }, new Rally { Name = "rally2" });
await context.SaveChangesAsync();
}
using (var context = new RallyDbContext(_options))
{
//When retrieve all rally records from the database
var service = new RallyService(context);
var rallies = service.GetAllRallies();
//Then records count should be 2
Assert.Equal(2, rallies.Count());
}
}
}
A working test application with this unit test is in my GitHub for your reference. I used SQL Express in the actual app.
I don't think it is standard to have a unit test constructor with a parameter. The unit test runner will new up this class, and unless you are using something that will auto-inject that parameter I think the test will fail to run.
Here is a standard fixture layout:
public class SampleFixture {
[Fact]
public void SampleShouldWork() {
// Arrange stuff we need for the test. This may involved configuring
// some dependencies, and also creating the subject we are testing.
var realOrSubstitutedDependency = new FakeDependency();
realOrSubstitutedDependency.WorkingItemCount = 42;
var subject = new Subject(realOrSubstitutedDependency);
// Act: perform the operation we are testing
var result = subject.DoWork();
// Assert: check the subject's operation worked as expected
Assert.Equal(42, result);
}
[Fact]
public void AnotherTest() { /* ... */ }
}
If you need a common setup between tests, you can use a parameterless constructor and do common initialisation there.
In terms of the specific class you are trying to test, you need to make sure your RallyDbContext is in a known state to repeatably and reliably test. You may want to look up answers specific to testing Entity Framework for more information.

Unit testing a started Service which has a few fields injected into it?

I am a Dagger newbie.
TL;DR:
If an Android Service has any fields injected into it using Dagger, then in order to actually perform the injection, I need to have an instance of that Service.
In Robolectric tests, this corresponds to MyService service = Robolectric.buildService(MyService.class).get(). And then, objectGraph.inject(service);
However, rest of the code that actually starts MyService still uses context.startService(context, MyService.class);.
Question: What is the idiomatic way in Dagger to address this mismatch?
Let's say I have a Service as follows:
public class MyService {
#Inject Parser parser;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
String data = intent.getStringExtra("data_to_be_parsed");
parser.parse(data);
}
}
Elsewhere in my code, I have an ApiClient class that does this:
public class ApiClient{
public static void parseInBackground(Context context, String data){
//This service does not have its fields injected
context.startService(new Intent(context, MyService.class).putExtra("data_to_be_parsed", data));
}
}
That parseInBackground method will be called from an Activity in response to user interaction.
Now, I'm following TDD and hence, I haven't yet written the Application Module for this. Here's the test module:
#Module(injects = MyService.class)
public class TestModule {
#Provides #Singleton Parser provideParser(){
return new MockParser();
}
}
And finally, the test case:
#RunWith(Robolectric.class)
public class ApiTest {
#Test
public void parseInBackground_ParsesCorrectly(){
//This service has its fields injected
MyService service = Robolectric.buildService(MyService.class).get();
ObjectGraph.create(new TestModule()).inject(service);
ApiClient.parseInBackground(Robolectric.application, "<user><name>droid</name></user>");
//Asserts here
}
}
As you can see, in the test, I retrieve an instance of the service and then inject the MockParser into it. However, the ApiClient class directly starts the service using an Intent. I don't have a chance to perform the injection.
I am aware that I can have MyService perform an injection on itself:
public void onCreate(){
ObjectGraph.create(new TestModule()).inject(this);
}
But then, I am hardcoding the TestModule here.
Is there an existing idiom in Dagger to set up dependencies for such situations?
It's the wrong way to hardcode your modules either in tests or in services. Better approach is to perform creation via your custom Application object which in turn will hold singleton ObjectGraph object. For example:
// in MyService class
#Override public void onCreate() {
super.onCreate();
MyApp.from(context).inject(this);
}
// in MyApp class
public static MyApp from(Context context) {
return (MyApp) context.getApplicationContext();
}
//...
private ObjectGraph objectGraph;
#Override public void onCreate() {
// Perform Injection
objectGraph = ObjectGraph.create(getModules());
objectGraph.inject(this);
}
public void inject(Object object) {
objectGraph.inject(object);
}
protected Object[] getModules() {
// return concrete modules based on build type or any other conditions.
}
Alternatively, you can refactor last method out into separate class and make different implementations for different flavors or build types. Also you may want to set overrides=true in your TestModule's annotation.

Laravel - Testing Repositories

I need to test a repository, which has a Eloquent model injected via constructor.
class EloquentOrderRepository implements OrderRepositoryInterface
{
protected $model;
public function __construct(Order $model)
{
$this->model = $model;
}
public function calculateValues(array $deliveryOption = null)
{
if (! is_null($deliveryOption)) {
$this->model->value_delivery = (float) number_format($deliveryOption['price'], 2);
}
$this->model->value_products = (float) number_format($this->model->products->getTotal(), 2);
$this->model->value_total = (float) $this->model->value_products + $this->model->value_delivery;
}
}
My problem is when I call $this->model->value_products (or any of the attributes). The Eloquent model try to call the setAttribute method, which doesn't exist on the mocked model. If I mock this method, I can't set the attribute correctly, and my test assertions will fail.
Here is my test:
<?php
class EloquentOrderRepositoryTest extends \PHPUnit_Framework_TestCase
{
protected $model, $repository;
public function setUp()
{
$this->model = Mockery::mock('Order');
}
public function test_calculate_values()
{
$repository = new EloquentOrderRepository($this->model);
$this->model->products = m::mock('SomeCollection');
$this->model->products->shouldReceive('getTotal')->once()->withNoArgs()->andReturn(25);
$this->model->calculateValues(array('price' => 12));
$this->assertEquals(12, $this->model->value_delivery);
$this->assertEquals(25, $this->model->value_products);
$this->assertEquals(37, $this->model->value_total);
}
}
Any thoughts on this?
I think your main issue is that you're not using the repository pattern correctly. You should think about the passed model in your constructor as a prototype. It's not a real thing to be worked with, but an instance of something you use for other things. In the repository, you may have a method getUnpaidOrders which will do something like return $this->model->wherePaid('0')->get();. As you can see, we're not interacting with the instance as an actual concrete instance but more of something to achieve a broader scope.
In your calculate method you're actually setting values on this prototype model. I don't know what you then intend to do with these but as far as I'm aware this is not what the repository patter is supposed to do. The methods on a repository are generally static-like methods, where you call them (maybe with some input) and get something back. They shouldn't have an effect on any kind of internal state as a repository shouldn't have any kind of internal state.
Hopefully this makes sense.

hooking into #EJB or #PersistenceContext injection in JAX-RS unit tests

I'm enjoying learning JAX-RS and Jersey, but I've hit a roadblock trying to test a simple resource that needs a DAO injected, something like this:
#Stateless
#Path("simple")
public class SimpleResource {
#PersistenceContext
private EntityManager em;
// #GET, etc...
}
(I'll be moving to a more abstracted DAO pattern, but the problem is the same, i.e., how do I inject the #EJB DAO?)
In my unit tests I'm using a embedded Jetty server that configures Jersey in its web.xml, and I'd like to hook into the resource's lifecycle so that I can inject a mock EntityManager, but I've not found a clean answer after a lot of searching. Can you help? Some possible directions I've come across:
1) Use JNDI context lookup in my code to get the DAO bean, and register the mock object in the tests.
Instead of #EJB or #PersistenceContext, use something like this in the resource's constructor:
theDAO = (DAOImpl) new InitialContext().lookup("java:global/EJB/DAOImpl");
However, that means my test environment needs to support JNDI, and doing so in Jetty will probably involve some pain. Plus, it doesn't use the clean annotation approach.
2) Use method injection.
Inject into the method so that I can set the DAO post-instantiation, e.g.,
#PersistenceContext(name = "persistence/pu00")
public void setPersistenceUnit00(final EntityManager em) {
em00 = em;
}
OR
private MyEjbInterface myEjb;
#EJB(mappedName="ejb/MyEjb")
public void setMyEjb(MyEjb myEjb) {
this.myEjb = myEjb;
}
However, to do this I need the Jersey-instantiated instance, e.g., SimpleResource. How do I get that?
3) Use reflection.
A kind of DIY injection, something like:
public static void setPrivateField(Class<? extends Object> instanceFieldClass, Object instance, String fieldName, Object fieldValue) {
Field setId = instanceFieldClass.getDeclaredField(fieldName);
setId.setAccessible(true);
setId.set(instance, fieldValue);
}
Again, I need the Jersey-instantiated instance.
4) Use an Injection Provider.
I'm still sketchy on how this works, but it looks like Jersey provides a means of defining customized injectable annotations, e.g.,
#Provider
public class EJBProvider implements InjectableProvider<EJB, Type> {
public ComponentScope getScope() {
return ComponentScope.Singleton;
}
public Injectable getInjectable(ComponentContext cc, EJB ejb, Type t) {
if (!(t instanceof Class)) {
return null;
}
try {
Class c = (Class) t;
Context ic = new InitialContext();
final Object o = ic.lookup(c.getName());
return new Injectable<Object>() {
public Object getValue() {
return o;
}
};
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
A variation using a helper class:
Server server = new Server(8080);
Context root = new Context(server,"/",Context.SESSIONS);
ResourceConfig rc = new PackagesResourceConfig("edu.mit.senseable.livesingapore.platform.restws.representations");
rc.getSingletons().add(new SingletonTypeInjectableProvider<javax.ws.rs.core.Context, Myobj>(Myobj.class, new Myobj(12,13)){});
root.addServlet(new ServletHolder(new ServletContainer(rc)), "/");
server.start();
With this use:
#Path("/helloworld")
public class HelloWorldResource {
#Context Myobj myClass;
....
}
Is this viable for #EJB or #PersistenceContext?
5) Extend javax.ws.rs.core.Application.
Sketchy on this, but:
#javax.ws.rs.ApplicationPath("application")
public class InjectionApplication extends javax.ws.rs.core.Application {
private Set<Object> singletons = new HashSet<Object>();
private Set<Class<?>> classes = new HashSet<Class<?>>();
public InjectionApplication() {
// no instance is created, just class is listed
classes.add(BookResource.class);
}
#Override
public Set<Class<?>> getClasses() {
return classes;
}
#Override
public Set<Object> getSingletons() {
return singletons;
}
}
6) Extend ServletContainer.
An older style of using InjectableProvider? Looks more complex:
public class ServletAdapter extends ServletContainer {
#Override
protected void configure(ServletConfig servletConfig, ResourceConfig rc, WebApplication wa) {
super.configure(servletConfig, rc, wa);
rc.getSingletons().add(new InjectableProvider<Resource, Type>() {
public ComponentScope getScope() {
return ComponentScope.Singleton;
}
public Injectable<Object> getInjectable(ComponentContext ic, Resource r, Type c) {
final Holder value = new Holder();
Context ctx = new InitialContext();
try {
value.value = ctx.lookup(r.name());
} catch (NamingException ex) {
value.value = ctx.lookup("java:comp/env/" + r.name());
}
return new Injectable<Object>() {
public Object getValue() {
return value.value;
}
};
}
});
}
}
7) Use an embedded EJB container.
E.g., http://openejb.apache.org. This is pretty heavy, and I expect it's going to be messy to get working. (In fact, what started me down the "Jetty + Jersey" route was a bug in GlassFish Embedded around security logins. I also looked at other Java EE 6 application containers like JBoss AS, but each had problems in embedded mode, with limited user community support.)
8) Use a third-party IoC library like Spring or Guice.
Spring is apparently commonly used for solving these kinds of problems (injecting mocks when unit testing), but I wanted to avoid having to learn another big set of APIs - pure Java EE has been enough of a challenge! But I'm game if it's the best solution. I haven't yet looked carefully into Spring or Guice.
Have you used any of these successfully? Any other solutions you like? I'm really looking forward to your advice on this. Thanks in advance -- matt
Since you are using Netbeans, give this a try:
Using the Embedded EJB Container to Test Enterprise Applications
The tutorial uses an embedded Glassfish container and injects an EJB that encapsulates the EntityManager (similar to what you described in your first option).
If you only need an EntityManager inside your embedded Jetty container, why use injection in the first place? You can just put one of the JPA implementations (such as eclipselink or hibernate) on your class-path, configure a resource local persistence unit, then obtain it like this:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("your unit name");
EntityManager em = emf.createEntityManager();
It would be enough to have something (maybe a static DAO factory?) that behaves like your #EJB for the purpose of testing your JAX-RS classes.
If you do want your unit tests to be as close to the Java EE environment as possible, look into running them with Arquillian (http://www.jboss.org/arquillian.html). It runs the tests directly on a Java EE container - it's easy, it has great documentation.

Create System.Data.Linq.Table in Code for Testing

I have an adapter class for Linq-to-Sql:
public interface IAdapter : IDisposable
{
Table<Data.User> Activities { get; }
}
Data.User is an object defined by Linq-to-Sql pointing to the User table in persistence.
The implementation for this is as follows:
public class Adapter : IAdapter
{
private readonly SecretDataContext _context = new SecretDataContext();
public void Dispose()
{
_context.Dispose();
}
public Table<Data.User> Users
{
get { return _context.Users; }
}
}
This makes mocking the persistence layer easy in unit testing, as I can just return whatever collection of data I want for Users (Rhino.Mocks):
Expect.Call(_adapter.Users).Return(users);
The problem is that I cannot create the object 'users' since the constructors are not accessible and the class Table is sealed. One option I tried is to just make IAdapter return IEnumerable or IQueryable, but the problem there is that I then do not have access to the methods ITable provides (e.g. InsertOnSubmit()). Is there a way I can create the fake Table in the unit test scenario so that I may be a happy TDD developer?
My current solution is to wrap the functionality I want from Table into a TableWrapper class:
public interface ITableWrapper<TEntity>
where TEntity : class
{
IEnumerable<TEntity> Collection { get; }
void InsertOnSubmit(TEntity entity);
}
And here's the implementation:
public class TableWrapper<TEntity> : ITableWrapper<TEntity>
where TEntity : class
{
private readonly Table<TEntity> _table;
public TableWrapper(Table<TEntity> table)
{
_table = table;
}
public IEnumerable<TEntity> Collection
{
get { return _table; }
}
public void InsertOnSubmit(TEntity entity)
{
_table.InsertOnSubmit(entity);
}
}
So now I can easily mock data from Collection, as well as keeping the functionality of InsertOnSubmit (any other functions that I need down the road can be added later on).
I have had success using the Data Access Layer to produce domain object collections and then using linq to objects.
The object under test then only relates to List, which is fairly easy to unit test.
I don't like when the logic entities should have Data Access Layer dependencies. They should stop at the service layer, if even there. I usually go for the model where the service layer invokes a data access object to get a List, passes that list into whichever logic object that needs it (if necessary uses linq-to-objects to filter out the relevant data and injects it into eiter a flat list, dictionary or an object model).
The business objects become very testable, even though they don't benefit from the richness of the inferred data model.