How to unit test the Private Actions in MVC application? - asp.net-mvc-3

Can we unit test the action which are having access specifier as private? If possible how can we unit test the private actions?

You can but why do you have private action methods? I'd rethink that architecture a little bit more. If you forget to make it private it becomes URL addressable.
However if you really want to do this right click on the method and add a unit test. The unit test project will add an item to the apps assemblyinfo.cs [InternalsVisibleTo] so it's private methods can be accessed via a proxy that's created in the test project.
It's a bit messy may as well pull that out into a separate class and make it public or internal etc

One option is make the action public and decorate it with NonActionAttribute.

Related

Executing extension before SpringExtension

I'm trying to implement integration testing in my app and have test class like that:
#ExtendWith(value={MyDockerExtension.class})
#ExtendWith(value={SpringExtension.class})
#WebAppConfiguration
#ContextConfiguration(classes={...})
#TestInstance(TestInstance.LifeCycle.PER_CLASS)
public class TestClass{ ... }
Is there any way to make MyDockerExtension execute some code, before whole SpringExtension start working and generate whole Context with Configurationc classes?
I've heard that order in which we declare extensions is the key, but sadly MyDockerExtension that implements BeforeAllCallback, AfterAllCallback executes right before test method and after whole context is loaded. In that situation it's to late to start containers with docker, becuase since whole context is loaded my app already tried to connect to the container.
At first I was skeptical about the order being fixed but you're correct:
Extensions registered declaratively via #ExtendWith will be executed in the order in which they are declared in the source code.
Regarding the MyDockerExtension, you may want to look at the extension point TestInstancePostProcessor, which is called before #BeforeAll. SpringExtension implements it and I guess it's there where it sets up the application context. If you also implement it, you should be able to act before it does.

Testing spring repositories

In the Spring Data I have found very helpful interface called JpaRepository. Because I need more functionality I decided to create my own interface of repository:
public interface BaseRepository<T, ID extends Serializable>
extends JpaRepository<T, ID> {
public <TA, TV> int deleteBy(SingularAttribute<T, TA> attr, TV val);
}
As you can see this is a generic interface. It works fine, but I would like to know how I can test it? Of course I can write integration test for each concrete repository but I am looking for better way.
As usual with testing, you should make sure you know what you're testing. Find answers to these questions:
Do you want to test the underlying database?
Do you want to test the Spring Data repository connector for this respository?
Do you want to test whether your code calls the correct methods on the interface?
Doing #1 is useless: The database vendor has already run thousands of tests on its product. There is rarely a reason to do this effort again.
Doing #2 is useless unless you suspect a bug in the code for Spring Data.
Which leaves us with #3. Use a mocking framework to make sure the method is called at the appropriate places (and maybe check the arguments, too).
That way, you can make sure your code behaves correctly.
If you notice the framework throwing errors or you notice that objects aren't deleted correctly, you can add more tests. But most of the time, this won't happen because of bugs in the database or Spring Data. Instead, your code won't call deleteBy() or it will call the method with the wrong arguments.

Unit Testing While Using Entity Framework

I have a web application that has been created using MVC 3 and Entity Framework. I would like to start using unit testing, but so far I have not been able to run any unit tests due to the way the system talks to the database.
I have a BaseController, which defines a DataContext as a variable:
public class BaseController : Controller
{
public Models.MyEntities DataContext = new Models.MyEntities();
Each controller then inherits the BaseController, thereby making the DataContext variable available to all controllers without redefining it:
public class ErrorController : BaseController
{
When I run a unit test, I receive an error about the object reference not being set to an instance of an object, each time referring to the line where I access DataContext.
Most references to unit testing say you should be abstracting your database layer, and using fake data for testing. This seems counter-intuitive to me, but that is a different discussion.
My question is - is it possible to use unit testing with the system configured the way it is? I am open to using any testing framework available, either MSTest, NUnit / XUnit etc.

Acceptance testing preloading of data into GAE dev server datastore

In my application I have a set of of DAOs which I inject into my application layer. For an acceptance test I'm writing, I want to preload the dev_server datastore with data, so I use the same Spring config in my JUnit test (using the #ContextConfiguration annotation) to inject an instance of the relevant DAO into my test. When I actually go to store some data eg:
dao.add(entity)
I get the dreaded "No API environment is registered for this thread."
Caused by: java.lang.NullPointerException: No API environment is registered for this thread.
at com.google.appengine.api.datastore.DatastoreApiHelper.getCurrentAppId(DatastoreApiHelper.java:108)
at com.google.appengine.api.datastore.DatastoreApiHelper.getCurrentAppIdNamespace(DatastoreApiHelper.java:118)
....
This is probably because my test case hasn't read in the GAE application-web.xml with the app details (although I'm guessing here I could really be wrong); so it doesn't know to write to the same datastore that the app running on the dev_server is reading/writing to.
How can I get my test to "point" to the same datastore as the app? Is there some "datasource" mechanism that I can inject both into the app and the test? Is there a way to get my test to force the datastore api to read the needed config?
Here is a page that talks about how to do unit tests that connect to a dev datastore. Is this the kind of thing you're looking for? Basically it talks about two classes, LocalServiceTestHelper and LocalDatastoreServiceTestConfig that you can use to set up an environment for testing. While the example given is for unit tests, I believe it will also work for your situation.
You can then configure things like whether the dev datastore is written to disk or just kept in memory (for faster tests). If you want this data to go to the same place as your dev server, you will probably want to adjust this, as I think the default is the "in memory" option. If you look at the javadoc there is a "setBackingStoreLocation" method where you can point to whatever file you want.
I've found the solution!!!!
For some reason the Namespace, AppID and the AuthDomain fields of the test datastore have to match that of the dev_server, then the dev_server can see the entities inserted by the test.
You can see the values for the environment (dev_server or test code) with the following statements
System.out.println(NamespaceManager.get());
System.out.println(ApiProxy.getCurrentEnvironment().getAppId());
System.out.println(ApiProxy.getCurrentEnvironment().getAuthDomain());
In your instance of LocalServiceTestHelper (eg: gaeHelper), you can set the values for the test environment
// the NamespaceManager is thread local.
NamespaceManager.set(NamespaceManager.getGoogleAppsNamespace());
gaeHelper.setEnvAppId(<the name of your app in appengine-web.xml>);
gaeHelper.setEnvAuthDomain("gmail.com");
Then the dev_server will see your entities. However because of synchronisation issues, if the test writes to the datastore after the dev_server has been started the dev_server wont see it unless it can be forced to reread the file (which I haven't figured out yet). Else the server has to be restarted.
I've found a workaround, although it's not very nice because each test method doesn't clean up the Datastore, as explained in the article Local Unit Testing for Java, however, the Datastore starts clean each time the Test class is run, so it's not so bad, provided that you're careful about that.
The problem is, that when using SpringJUnit4ClassRunner, the spring environment is created before the #Before annotation can be run, the solution is use #BeforeClass and use a static variable for LocalServiceTestHelper, to have them created before the Spring Environment is set up.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:META-INF/spring/context-test.xml")
#Transactional
public class MyTest {
#Inject
private MyService myService;
private static final LocalServiceTestHelper helper =
new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());
#BeforeClass
public static void beforeClass() {
helper.setUp();
}
#AfterClass
public static void afterClass() {
helper.tearDown();
}
If anyone has a better solution, I'll be glad to hear!

Reasonable to remove TestContext from a unit test?

All my unit test classes have been created by Visual Studio 2008 from a built-in unit test template that includes a "TestContext" property. So far I have not used a test context and this field is upsetting Resharper and code coverage.
Is it ok to remove TestContext or would doing that indicate my unit tests are poorly structured?
If you don't need it, remove it. You can always introduce it again afterwards. I've hardly used it too...
No harm in retaining the TestContext property, particularly if your unit test class makes use of data-driven test methods. Particularly useful if you use this type of statement:
Assert.AreEqual(myValue, this.TestContext.DataRow["ExpectedValue"].ToString())
Conversely, if you're using a hand-coded test class (i.e. not one generated by the VS "Add New Item" menu option), adding a property declaration as follows gives you instant access to the record of test data as it relates to the current unit test:
public TestContext TestContext { get; set; }
Hope that helps!

Resources