How to test a Service Layer in MVC4? - asp.net-mvc

I have a web application with three layers: Web > Services > Core. I've just added a Services.Tests unit tests project and I'm trying to figure out how to get started.
I've added a reference from the Services.Tests project to the Services project. I then created an instance of the Services.service class in my Test class:
[TestClass]
public class CrudTests
{
private readonly SetServices _setService = new SetServices();
[TestMethod]
public void TestMethod()
{
But I got an error about _setService needing a reference to my Core project.
First question: Why do I need to reference my core project if the Services project already references it?
I've added the reference and ran the empty test, which passed. I then tried to call one of the basic methods within my service class:
[TestMethod]
public void TestMethod()
{
_setService.CreateSet("Test Set", "Test Set Details", null);
But I get a providerIncompatileException.
Second question: What is the recommended way to create/use a dedicated test database?
Third question: How do I tell my tests project which database to use?

By parts,
Why do I need to reference my core project if the Services project already references it?
Project references aren't inheritable, as per this answer. The fact that Services has a dependency on Core does not imply that whoever consumes Services needs to know anything about Core, or for that matter uses any logic exclusively defined in Core.
What is the recommended way to create/use a dedicated test database?
It depends entirely on what database, what ORM, what framework, etc. There aren't fixed ways to do it.
How do I tell my tests project which database to use?
In the same way you tell the application to do it: through the configuration. Simply create a DatabaseStub and hard-code the test database information in it.

Related

Complete guide on how to use Migrations with several Azure SQL databases, connectionstrings and Azure App Services publish profiles

I have a MVC project hosted in Azure App Services with Azure SQL databases for the data. I have a development, staging/acceptance and production environment (App Service) and as for the databases i have development, staging/acceptance, production and a local DB (mdf). I have 3 publish profiles (1 for each environment).
I (think) to understand that i can use the CTOR of the DbContext class to set a connectionstring from the web.config based on the name:
Ex.
public ApplicationDbContext(): base("DbContextNameThatResidesInWebConfig")
{
// ...
}
If i am not using migrations i am able to do what i want without any issues. When using migrations (since i don't want any data loss when changing my model) i am getting several issues on model creation, i tried using several methods in my above CTOR:
// this is a custom Seeder that inherits DropDatabaseAlways/WhenModelChanges
System.Data.Entity.Database.SetInitializer(new ContractCareSeeder());
// from what i understand, this tells to use the latest migrations applied
System.Data.Entity.Database.SetInitializer(new MigrateDatabaseToLatestVersion<ApplicationDbContext, Migrations.Configuration>());
Configuration.cs:
internal sealed class Configuration : DbMigrationsConfiguration<ApplicationDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
// seeding method ...
}
But i always receive errors like, "there is already a table called XXX ..." even when i have succesfully executed the Update-Database command in the console it still fails.
I am quite lost in this and can't seem to find what is the best way of handling my scenario. I want to be able to use multiple publish profiles (later on we will use development slots but not now) and there there is also configuration possible. I can see all my connections from my web.config along with update database checkbox but i can't seem to find the right way of configuring everything together...
Can anyone assist me, suggest me or provide any help of any kind?
Kind regards!
ASP.NET 5 introduces improved support for controlling application behavior across multiple environments, such as development, staging, and production. Environment variables are used to indicate which environment the application is running in, allowing the app to be configured appropriately.
You could set ASPNET_ENV with the current environment you want to use. If you need to check whether the application is running in a particular environment, use env.IsEnvironment("environmentname")
if (env.IsDevelopment())
{
app.UseBrowserLink();
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
For more details you could refer to this article and this one which though is asp.net core.

Symfony 3.4.4 + Sonata ADmin Bundle + already existing entities

I'm starting with Symfony 3.4.4 + SonataAdmin Bundle.
Everything works correctly for me.
I already have entities generated and in the integration of entities within SonataAdmin bundle by means of "php bin/console sonata:admin:generate" entities are generated in "src/AppBundle/Resources/config/services.yml
And that file is not integrated into my bundle.
I have read that using Dependency Injection is the most correct way to load that file, but I do not know how it is done.
Can someone explain to me how to install dependency injection and that this file be loaded correctly by means of the "good practices" of symfony?
I think you are confusing something.
Dependency injection is a principle in software development to decouple a classes dependency from other classes by not setting properties inside a class directly. Instead you give it for example to the constructor or set it afterwards by a public setter method. With this your classes are replaceable and thats beneficial especially for testing your source code.
So you cant install a software development principle.
And your entities are not generated in your services.yml. Your services are defined here and your entities normally going to src/AppBundle/Entity.
Symfony/Sonata is using dependency injection by defining services in the services.yml and telling them, which parameters they will get.
For example
services:
mailer:
class: Mailer
arguments: ['%mailer.transport%']
Here the mailer.transport parameter will be injected to the Mailers class constructor.
There are many yml files in your app/config folder, but the all are united in the config.yml
So if you have no instruction like
- { resource: "#AppBundle/Resources/config/services.yml" }
in your app/config/config.yml your services will never be loaded.

What does Grails create-service do exactly?

I am developing a Grails application (with Grails 1.3.7). In service layer, I did not use the command 'create-service' to create my service but do it manually.
As the result, my service was not auto initialize in controllers and other services, and it did not handle transaction.
But I do not know where is the differences from create service by command with by manual? Because I do not see any configuration file which figure out this? (I mean in traditional Spring, we always have some configuration files which specify all beans in applications, but in Grails is not).
I want to fix this issue and commit to SVN server my fix, but I do not want to delete the old service and commit the new one which is created by Grails command. So could you please help me:
1. explain what is the differences from create service by command with by manual?
2. how to change the the service created by manual to service created by command without replacing the old one?
Thank you so much!
explain what is the differences from create service by command with by manual?
Assuming you put your service in grails-app/services and followed the naming convention using a postfix of Service The only difference is that you get a nice template that looks like
class SomeService {
boolean transactional = true
def someMethod() {
}
}
and it automatically creates a unit test with the name SomeServiceTests. That is it. BTW transactional defaults to true if you do not include it.
how to change the the service created by manual to service created by command without replacing the old one?
There is nothing to do assuming you followed the conventions. If you did follow the conventions and you are still experience problems please update your question with more details such as how are you trying to use your service and a example of your service.
As long as you put your class in the grails-app/services directory, it should act just like any other service (and work as a spring bean).
If you put it in src/java or src/groovy, it's not considered a service (and not loaded as a service artefact by grails). It could still be a spring bean, but you'd have to manually add it to the resources.groovy file.
Also note that the Grails autowiring of the beans must be exact, so if you have MyService and you want to use it in the controller, make sure you have "def myService" or "MyService myService." If you would prefer different names of your member variables, you can also use the Spring Autowired annotation directly, though I've only tried autowiring grails types (e.g. a grails service) autowired to a bean I declared in resources.xml
If you put services, or any other bean in the resources.xml or resources.groovy files, they will also be autowired intro controllers, other services, etc.
It's best to think of Grails as "rapid Spring", so the autowiring, transactions, etc all are backed by Spring configuration and such.

How to create unit tests for EJB 3.0 based code to be deployed in jboss 5.1?

Greetings,
I am interested in adding test coverage for an existing application. The technologies involved include EJB 3.0, jboss 5.1, Hibernate and MySQL. This project is built using Ant. The goal is to provide test coverage to this application to allow further features to be added with confidence.
Initial searches give several ideas, but I have yet to find an tutorial or a start to finish set up steps to create an initial unit test.
I found EJB3Unit to be promising.
http://ejb3unit.sourceforge.net/Installation.html
However, the examples to setup are for maven and we are using Ant.
If anyone could help with how to setup a simple example test with EJB3Unit and Ant it would be very helpful.
Thanks for your time,
Conor
You will have to ask yourself "What exactly am I trying to test?" first.
If you want to test your EJB3 in isolation, remember that an EJB3 is just a POJO. You can call the class directly from a jUnit test method.
If you want to test your EJB, the Application server, the Container, AND your network (if #Remote annotation is used) then you can write an integration test class that looks up the #Remote or #Local EJB in the JNDI tree of your container like so:
#Test
public void callEjb() throws Exception {
Context context = new InitialContext();
YOUR_EJB_CLASS myEjb = (YOUR_EJB_CLASS) context
.lookup(JNDI_PATH_FOR_YOUR_EJB);
myEjb.myMethod();
}
If you want to test your EJB as an EJB and separate from an EJB Container, then EJB3 could be what you are looking for instead.
P.S. Don't let Maven scare you. I haven't used it yet, but it seems that it is gaining in mind-share over ant.

Connection string in unit test project to reference database in app_data folder

I am looking to reference my database file in my unit test project. This is an ASP.NET MVC app.
Please note: I know I should not be accessing the database in my unit tests but this is for a quick fix on one test that I need to have pass just now.
After the next milestone I will be mocking the database access methods etc.
So here is my connection string in my mvc app web config and the unit test ap.config files
<add name="DBConnectionString" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\DB.MDF;Integrated Security=True;User Instance=True"
providerName="System.Data.SqlClient" />
When I run the test I get an error:
Test method
ED.Tests.Controllers.CandidateControllerTest.PersonalDetailsStepPostShouldRedisplayIfNoSurnameSupplied
threw exception: System.Data.SqlClient.SqlException:
An attempt to attach an auto-named database for file C:\Users\Desktop\ED\TestResults\LAPTOP-D 2009-07-22 18_16_20\Out\DB.MDF failed.
A database with the same name exists, or specified file cannot be opened, or it is located on UNC share.
It seems to me the connection string is wrong but I'm not sure how to set the path properly. I have tried adding \..\.. and the directory names etc.
MSTest will run your unit test assembly in a completely different folder on every test run. The idea is that each run is a completely isolated case from previous and subsequent runs. It's actually kind of a pain to tell it to copy data files along with the rest of your application. You need to right-click on your solution (not your project), choose add, create a new test run configuration. Then you need to edit the test run configuration and specify which files will be copied to the test execution folder. There should be a sibling directory to your solution directory called TestResults which contains the folders used for each test run.
you can simply reference localdb like this:
<add name="DefaultConnection"
connectionString="Server=(localdb)\v11.0;Database=WebPortalDb" providerName="System.Data.SqlClient"/>
where WebPortalDb is your database name.
Comment to Craig's answer: It shouldn't be a pain to deploy extra data files for unit test execution. You can use DeploymentItemAttribute (Microsoft.VisualStudio.TestTools.UnitTesting) at class or method levels to specify which files need to be copied prior to running those tests.
The best answer is not to connect to a database at all with some Unit Tests, and instead mock the database. However, you may need to refactor existing MVC code to get to a point where you CAN mock a database dependency, and you should never refactor until your code is wrapped in some tests. So in that situation, yes - you'll probably need to connect your test project to the database, at least for a while until you decouple everything enough to enable mocking.
So in my instance I was using ASP.Net MVC 5. This meant I could get the necessary Entity Framework config added to the Unit Test Project's app.config file simply by Right-Clicking on the Solution file, Managing NuGet for Solution, and adding EF to the test project.
Then adding the connection string from the MVC project's main Web.config file NEARLY worked, with the minor tweak that I had to remove the final part of the string that said:
AttachDbFilename=|DataDirectory|<<MY_DATABASE_NAME_AND_ID>>.mdf
As I say, creating 'Unit' tests that connect to a database is not the way to go, so this will only be a temporary measure. But the code needs refactoring to get it to a mockable state, and (s)he who refactors without at least a few tests to prove the refactoring hasn't broken everything is cruising for a bruising.

Resources