Where should I place this code in MVC? - unit-testing

My code works perfectly, BUT. Whats the best practice in this case?
Here is the code that is important.
This is in the controller.
private IProductRepository repository;
[HttpPost]
public ActionResult Delete(int productId) {
Product prod = repository.Products.FirstOrDefault(p => p.ProductID == productId);
if (prod != null) {
repository.DeleteProduct(prod);
TempData["message"] = string.Format("{0} was deleted", prod.Name);
}
return RedirectToAction("Index");
}
This is the repository (both Interface etc)
public interface IProductRepository {
IQueryable<Product> Products { get; }
void SaveProduct(Product product);
void DeleteProduct(Product product);
}
And here comes the repository..... (the part that is important) I want to point out though... that this is not a fakeclass as is pretty clear. The testing is done on fakeclasses.
private EFDbContext context = new EFDbContext();
public IQueryable<Product> Products {
get { return context.Products; }
}
public void DeleteProduct(Product product) {
context.Products.Remove(product);
context.SaveChanges();
}
Well first question:
When doing testing on this, I will make a two TestMethods on the Controller in "ControllerTest". "Can_delete_valid_product" and "Cannot_delete_invalid_product". Is there any point in having a testclass for the repository? Like "RepositoryTest", afterall the controller tests if the deletefunction works no need to test it twice right?
Second question:
In this I test in the controller if the product exists, before trying to delete it. If it exists I call the deletefunction in the repository. This means that there should never be the posibility of an exception. BUT you could still create an exception in the repository if you send down null. (which cant happen here but you could still do it if you forget to check if null). Question is if the testing if product exists should be done in the repository instead?

I prefer to keep logic out of the controller for the most part. A test of the controller action verifies if the repository is called, but the repository itself is mocked in that test. I would make the repository responsible for handling null checking.

Personally I create separate tests for my repositories/data access to ensure that it works properly. The controllers themselves would be tested with mocks.
Actually it's entirely possible (just maybe not that likely) that someone could delete a product just as someone else is trying to delete it. In this case you probably don't care/need to know that someone did though so I would probably just swallow that exception in the repository (though I would log it first). In terms of null checking/defensive programming that's entirely a personal choice. Some people leave checks like that to the entry points of the system where as others will build a layered defense that has additional checks throughout the code. The problem is that these checks can get quite ugly which is a big part of why I wish Code Contracts would gain more traction.

This means that there should never be the posibility of an exception. BUT you could still create an exception in the repository if you send down null. (which cant happen here but you could still do it if you forget to check if null).
Or if it's deleted after you check it exists but before you delete it. Or if you lose connection to the repository (or will the method never return in this case?). You can't avoid exceptions in this way.

Related

Service #Transactional exception translation

I have a web service with an operation that looks like
public Result checkout(String id) throws LockException;
implemented as:
#Transactional
public Result checkout(String id) throws LockException {
someDao.acquireLock(id); // ConstraintViolationException might be thrown on commit
Data data = otherDao.find(id);
return convert(data);
}
My problem is that locking can only fail on transaction commit which occurs outside of my service method so I have no opportunity to translate the ConstraintViolationException to my custom LockException.
Option 1
One option that's been suggested is to make the service delegate to another method that's #Transactional. E.g.
public Result checkout(String id) throws LockException {
try {
return someInternalService.checkout(id);
}
catch (ConstraintViolationException ex) {
throw new LockException();
}
}
...
public class SomeInternalService {
#Transactional
public Result checkout(String id) {
someDao.acquireLock(id);
Data data = otherDao.find(id);
return convert(data);
}
}
My issues with this are:
There is no reasonable name for the internal service that isn't already in use by the external service since they are essentially doing the same thing. This seems like an indicator of bad design.
If I want to reuse someInternalService.checkout in another place, the contract for that is wrong because whatever uses it can get a ConstraintViolationException.
Option 2
I thought of maybe using AOP to put advice around the service that translates the exception. This seems wrong to me though because checkout needs to declare that it throws LockException for clients to use it, but the actual service will never throw this and it will instead be thrown by the advice. There's nothing to prevent someone in the future from removing throws LockException from the interface because it appear to be incorrect.
Also, this way is harder to test. I can't write a JUnit test that verifies an exception is thrown without creating a spring context and using AOP during the tests.
Option 3
Use manual transaction management in checkout? I don't really like this because everything else in the application is using the declarative style.
Does anyone know the correct way to handle this situation?
There's no one correct way.
A couple more options for you:
Make the DAO transactional - that's not great, but can work
Create a wrapping service - called Facade - whose job it is to do exception handling/wrapping around the transactional services you've mentioned - this is a clear separation of concerns and can share method names with the real lower-level service

Unit testing against repositories, with MSpec, am I doing this right?

A second MSpec question from me in a day, this is a new record. I'm trying to get smart on MSpec very quickly and I've run into some old problems I've always had with MSpec.
Scenario: I have a repository that contains a bunch of cartoons. Right now I only need to filter this set on a single Name parameter, which is a string. As I'm told I'll need to filter this on more properties later on, I decide to create a class which takes in my ICartoonRepository via IoC, and contains a simple method that's called GetByName(string name).
You might argue this is overkill, but I'm trying to teach myself how to use MSpec and work in a more TDD manner.
So I create the following:
[Subject(typeof(CartoonViewModelBuilder))]
public class when_cartoon_repository_is_asked_to_get_by_id : specification_for_cartoon_viewmodel_builder
{
static string name;
static Cartoon the_cartoon;
static Cartoon result;
Establish context = () =>
{
name = "Taz";
the_cartoon = new Cartoon();
the_cartoon_repository.Stub(r => r.GetAll().Where(x=>x.Name == name).FirstOrDefault()).Return(the_cartoon);
};
Because of = () => result = subject.GetByName(name);
It should_return_cartoon = () => result.ShouldBeTheSameAs(the_cartoon);
}
This fails on the stub as the repository is empty. I have a couple other tests that pass fine (simply testing the GetAll(), etc). Do I need to add things to the repository to test it? This is where I'm stumped, please be gentle.
Also, if I'm writing the linq statement in the stub, it seems like I'm doing it twice, in the actual implementation and in the test. Is this the point? It doesn't feel right. Is there a better way I can write this test?
For clarity sake, here is the actual implementation (I'm omitting the interface and the class, which just has one property:
public class CartoonViewModelBuilder: ICartoonViewModelBuilder
{
readonly ICartoonRepository _cartoonRepository;
public CartoonQueryObject(ICartoonRepository cartoonRepository)
{
_cartoonRepository = cartoonRepository;
}
public IList<Cartoon> GetAllCartoons()
{
return _cartoonRepository.GetAll();
}
public Cartoon GetByName(string name)
{
return _cartoonRepository.GetAll().Where(x => x.Name == name).FirstOrDefault();
}
}
Edit 1: Based on the lack of responses, I should say that if I were using something like NUnit, I would be creating a method on the testing class that was like, "LoadDummyData" and threw data into the repository, then I'd do complex filtering or view model building and sort of manually checked what happened. This made large refactoring a chore. It seems like specs allows you to avoid that?
Edit 2: Here's my corrected test which now passes. Let me know if I'm doing it right, I think I am. Thanks again for the hand holding!
static string name;
static Cartoon the_cartoon;
static Cartoon result;
static IQueryable<Cartoon> the_cartoons;
Establish context = () =>
{
name = "Taz";
the_cartoon = new Cartoon {Name = name};
the_cartoons = new List<Cartoon> {the_cartoon, new Cartoon(), new Cartoon() }.AsQueryable();
the_cartoon_repository.Stub(r => r.GetAll()).Return(the_cartoons.ToList());
};
Because of = () => result = subject.GetByName(name);
It should_return_cartoon = () => result.ShouldBeTheSameAs(the_cartoon);
Edit 3: Gave you both points, but I can only award one best answer unfortunately.
The actual reason of this test failing is the way you're mocking your repository. I would be very surprised if method chains like r.GetAll().Where(x=>x.Name == name).FirstOrDefault() could be mocked so easily, as it uses LINQ extension methods and lambda clauses. The framework should really throw NotSupported exception or something to let you know that you can't mock LINQ queries as a whole.
To mock LINQ query result, you should provide properly prepared underlying data collection, which is the starting point of LINQ query. In your example you should mock just r.GetAll() to return a collection containing your element with proper name. The actual query will run on your "mocked" data and retrieve the object you expect.
This removes the need to duplicate your LINQ query in code and in test, what is strange, as you noted.
EDIT: Code in your edit is like I've suggested, technically OK.
Anyway, by now it's a bit overkill, as you've said. Your class under test doesn't do anything beside the call to the mocked repository, so the value of that test is rather small. But it may be a good start if you're going to have some more logic in GetByName method.
If you want to test your repository implementation, don't stub it! MSpec or not, I would add a list of known items to the repository and then issue the query with GetByName. Then assert that just the item you expect was returned. I would also use ShouldEqual as the repository might work with the items you add and return a different instance, though considered equal (aggregate IDs are equal).

mspec & rhino mocks expected exception testing

I'm fairly new to unit testing and can't get around how to test (or if I even should) this case properly.
I have a controller method (pseudo code):
public ActionResult Register(formModel model)
{
if (ModelState.isValid) {
try {
_userService.CreateUser(a bunch of parameters here);
return RedirectToAction(some other action);
}
catch (Exception e)
{
ModelState.AddModelError("",e.Message);
}
}
return View();
}
I have a bunch of separate tests against "_userService". The "CreateUser" method just creates a new user and returns nothing OR throws an exception if there was an error (ex. the user exists) that I bubble up to the controller surround in a try catch and add the exception to the ModelState.
From what I understand I should mock the service and assert that it was called correctly (i use the assertwascalled syntax) since it returns nothing and I just want to know that my controller calls it.
What I'm not sure is how to test that when the userservice throws an error it should not redirect and should add that exception to the modelstate. With rhino mocks you can stub a mock but the book art of unit testing advises against that.
Right now in my test I manually add a model error (not caring if it's from user service) and test that the controller returns the same view if there are errors. Is this the correct way of going about this? Or should I maybe create a separate test where I stub the _userService to throw an error and check it gets added to modelstate? Or should I not even test that case? I feel like I may be just over analyzing the whole thing and testing using the modelstate would be enough to satisfy this...
Your mock represents a collaborating class. I wouldn't get too hung up on the difference between mocks and stubs; it's still a collaborating class.
You can think of your unit tests as describing how to use your class, and how the class then interacts with its collaborators. You have two examples:
Given a controller
When I register the model
Then the class should ask the user service to create a user.
And:
Given a controller
Given the user service is broken
When I register the model
Then the class should attach the error to the model state.
It's that second Given that tells you you're stubbing rather than mocking. You're setting the user service up as though it's broken. The context in which the class acts is different, so you need to stub, and you should indeed throw an exception.
If you put these lines as comments inside your test, it'll make sense. If it makes sense, ignore the book.
BTW, this is unit-level BDD. You can use "Given, When, Then" at a unit level just as at a scenario level, and it might help you think about the logic of your tests. Just don't use BDD scenario tools for this.

Correct way to unit test private variables

I have the following method:
private string _google = #"http://www.google.com";
public ConnectionStatus CheckCommunicationLink()
{
//Test if we can get to Google (A happy website that should always be there).
Uri googleURI = new Uri(_google);
if (!IsUrlReachable(googleURI, mGoogleTestString))
{
//The internet is not reachable. No connection is available.
return ConnectionStatus.NotConnected;
}
return ConnectionStatus.Connected;
}
The question is, how do I get it to not try the connection to Google (thus avoiding the dependency on the internet being up).
The easiest way is to take _google and change it to point to something local to the machine. But to do that I need to make _google public. I would rather not do that because _google should not ever be changed by the app.
I could make `_google' a param to an overloaded version of the method (or object constructor). But that too exposes an interface that I don't ever want the app to use.
The other option is to make _google internal. But for the app, internal is the same as public. So, while others cannot see _google, the app interface still exposes it.
Is there a better way? If so, please state it.
(Also, please don't pick on my example unless it really helps figure out a solution. I am asking for ideas on general scenarios like this, not necessarily this exact example.)
Refactor your code to depend on an ICommunicationChecker:
public interface ICommunicationChecker
{
ConnectionStatus GetConnectionStatus();
}
Then your test(s) can mock this interface making the implementation details irrelevant.
public class CommunicationChecker : ICommunicationChecker
{
private string _google = #"http://www.google.com";
public ConnectionStatus GetConnectionStatus()
{
//Test if we can get to Google (A happy website that should always be there).
Uri googleURI = new Uri(_google);
if (!IsUrlReachable(googleURI, mGoogleTestString))
{
//The internet is not reachable. No connection is available.
return ConnectionStatus.NotConnected;
}
return ConnectionStatus.Connected;
}
}
Why do you have _google hard coded in your code? Why not put it in a configuration file which you can then change for your test for example?
Some options:
make _google load from an external configuration (maybe providing www.google.com as a default value) and supply a special configuration for unit tests;
place the unit test class inside the class containing the CheckCommunicationLink method.
Note: I would strongly recommend making it configurable. In real-world cases relying on the availability of a particular 3rd party web site is not a good idea, because they can be blocked by a local firewall etc.
For unit testing purposes you should mock whatever http connection you are using in your class (which is hidden in IsUrlReachable method). This way you can check that your code is really trying to connect to google without actually connecting. Please paste the IsUrlReachable method if you need more help with mocking.
If the above solution is not an option, you could consider having a local test http server and:
Making the url configurable, so that you can point to the local address
(this one is nasty) Use reflection to change _google before the tests
(most purist will disagree here) You could create an overload taking the parameter and use this one for testing (so you test only CheckCommunicationLink(string url) method
code for (3):
private string _google = #"http://www.google.com";
public ConnectionStatus CheckCommunicationLink()
{
return CheckCommunicationLink(_google);
}
public ConnectionStatus CheckCommunicationLink(string url)
{
//Test if we can get to Google (A happy website that should always be there).
Uri googleURI = new Uri(url);
if (!IsUrlReachable(googleURI, mGoogleTestString))
{
//The internet is not reachable. No connection is available.
return ConnectionStatus.NotConnected;
}
return ConnectionStatus.Connected;
}

How do you organise your MVC controller tests?

I'm looking for tidy suggestions on how people organise their controller tests.
For example, take the "add" functionality of my "Address" controller,
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Add()
{
var editAddress = new DTOEditAddress();
editAddress.Address = new Address();
editAddress.Countries = countryService.GetCountries();
return View("Add", editAddress);
}
[RequireRole(Role = Role.Write)]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Add(FormCollection form)
{
// save code here
}
I might have a fixture called "when_adding_an_address", however there are two actions i need to test under this title...
I don't want to call both actions in my Act() method in my fixture, so I divide the fixture in half, but then how do I name it?
"When_adding_an_address_GET" and "When_adding_an_address_POST"?
things just seems to be getting messy, quickly.
Also, how do you deal with stateless/setupless assertions for controllers, and how do you arrange these wrt the above? for example:
[Test]
public void the_requesting_user_must_have_write_permissions_to_POST()
{
Assert.IsTrue(this.SubjectUnderTest.ActionIsProtectedByRole(c => c.Add(null), Role.Write));
}
This is custom code i know, but you should get the idea, it simply checks that a filter attribute is present on the method. The point is it doesnt require any Arrange() or Act().
Any tips welcome!
Thanks
In my opinion you should forget about naming your tests after the methods you're testing. In fact testing a single method is a strange concept. You should be testing a single thing a client will do with your code. So for example if you can hit add with a POST and a GET you should write two tests like you suggested. If you want to see what happens in a certain exceptional case you should write another test.
I usually pick names that tell a maintainer what he needs to know in Java:
#Test public void shouldRedirectToGetWhenPostingToAdd(){
//...
}
You can do this in any language and pick any *DD naming convention if you like, but the point is that the test name should convey the expectations and the scenario. You will get very small test this way and I consider this a good thing.
Well, 13 months later and no answers. Awesome.
Heres what i do now:
/tests/controllers/address/add/get.cs
/tests/controllers/address/add/valid.cs
/tests/controllers/address/add/invalid.cs