Unit Testing in MVC not creating/accessing database - asp.net-mvc

I have a solution with an MVC project containing a Services project on top of a Core project.
I just added a Unit Tests project and referenced Core and Services - I'm trying to test Services.
I have a basic call in the test:
public class CrudTests
{
private readonly SetServices _setService = new SetServices();
[TestMethod]
public void TestMethod()
{
_setService.CreateSet("Test Set", "Test Set Details", null);
Which ends up failing because the test can't connect to a database. My config has this:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=.\;Initial Catalog=Project.Services.Tests;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\Project.Services.Tests.mdf" providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
I've tried by creating the database Project.Services.Tests and then running, but I get this:
Message=Database 'C:\Program Files\Microsoft SQL
Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\App.Services.Tests.mdf'
already exists. Choose a different database name. Cannot attach the
file
'C:\PROJECTS\App\App\Services.Tests\bin\Debug\Services.Tests.mdf'
as database 'App.Services.Tests'.
Source=.Net SqlClient Data Provider
ErrorCode=-2146232060
Class=16
LineNumber=65536
Number=1801
Procedure=""
Server=.\
State=2
StackTrace:
I tried deleting the database and letting the test do it's thing, and I get this:
A file activation error occurred. The physical file name
'\Project.Services.Tests.mdf' may be incorrect. Diagnose and correct
additional errors, and retry the operation.
How can I get this working properly?

In Unit Testing you must test the code without any dependency such as database or file system etc.
unit test means testing only that part of code independently.
if you want to test your code by its integration to database you must create Integration Test.
that means you should create an initializing for database usage before running test and a tear down for diposing resources after finishing tests.
maybe this link help you more to understand the difference between Unit Test and Integration Test

you should just fix the connection string and it should work, You are attaching the database file from |DataDirectory| of the test project,

Related

Passing environment variables to tests in Visual Studio 2019

Seems like a pretty trivial question, but to my surprise I found no mention of this on the web.
I've got an Nunit test project (that someone else wrote and I don't want to change too much), that I need to debug. These tests depend on environment variables that they read using Environment.GetEnvironmentVariable.
My question is: is there a way I can pass environment variables when debugging tests in Visual Studio?
I know I can pass environment variables when I debug an executable project through Project Properties->Debug, but this doesn't take effect when running tests (e.g. via Test Explorer). I also know I can pass test parameters through a .runsettings files, but these are accessible only through the TestContext class.
I also know I can pass test parameters through a .runsettings files, but these are accessible only through the TestContext class.
You can also specify environment variables in the .runsettings file:
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<RunConfiguration>
<EnvironmentVariables>
<YOUR_VARIABLE>Value for your variable</YOUR_VARIABLE>
<SOME_OTHER_VARIABLE>With another Value</SOME_OTHER_VARIABLE>
</EnvironmentVariables>
</RunConfiguration>
</RunSettings>
Alternatively (if you need to run code or calculate the value) you can implement a DataCollector which provides environment variables via ITestExecutionEnvironmentSpecifier
// Add a reference to nuget package `Microsoft.TestPlatform.ObjectModel`
// The assembly name must end with `Collector` (i.e. match `*collector.dll`)
[DataCollectorFriendlyName("my own example collector")]
[DataCollectorTypeUri("datacollector://myown/examplecollector/1.0")]
public class MyDataCollector : DataCollector, ITestExecutionEnvironmentSpecifier
{
public override void Initialize(
XmlElement configurationElement,
DataCollectionEvents events,
DataCollectionSink dataSink,
DataCollectionLogger logger,
DataCollectionEnvironmentContext environmentContext)
{
// inspect configurationElement for your custom settings
}
public IEnumerable<KeyValuePair<string, string>> GetTestExecutionEnvironmentVariables()
{
return new Dictionary<string, string>
{
["YOUR_VARIABLE"] = "your value",
};
}
}
You also configure your data collector via the .runsettings file:
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<RunConfiguration>
<TestAdaptersPaths>path/where/to/find/your/collector</TestAdaptersPaths>
</RunConfiguration>
<DataCollectionRunSettings>
<DataCollectors>
<DataCollector friendlyName="my own example collector" uri="datacollector://myown/examplecollector/1.0">
<Configuration>
<SomeSettingHere/>
</Configuration>
</DataCollector>
</DataCollectors>
</DataCollectionRunSettings>
</RunSettings>
If you want to change the environment vaiable when you are debugging a project without break it, you can try to set it in the system environment variable.
1), create a system environment variable called number
2) use this in your code:
string str= Environment.GetEnvironmentVariable("number",EnvironmentVariableTarget.Machine);
It will get the system environemnt variable number in your code.
3) start debugging this project and set a breakpoint on it, when you want to change the variable, you can change the value on the system environemnt variable number directly under Computer's properties.
After that,just move the cursor back to the code line, you can use the changed value.
=========================================
Update 1
When you change the value of system variable number, you should click OK to save the new value. And then move the cursor of the breakpoint back to get the new value.
Also, you should enable Edit and Continue option.

Using connectionstring from app.config with FSharp.Data.SqlClient

I'm using FSharp.Data.SqlClient and trying to move my connectionString from a [<Literal>] to the app.config.
My app.config looks like this
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Test;Integrated Security=True" providerName="System.Data.SqlClient"/>
</connectionStrings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
</startup>
</configuration>
And my SqlCommandProvider looks like the below, which should be correct according to http://fsprojects.github.io/FSharp.Data.SqlClient/configuration%20and%20input.html
new SqlCommandProvider<"SELECT ...",
ConnectionStringOrName = "name=DefaultConnection",
SingleRow = true,
AllParametersOptional = true>(??????)
Now the question is. What goes in the last part, the ?????? part.
I tried "name=DefaultConnection" but it gives me a runtime error with name being unsupported.
I can't seem to find any documentation explaining what goes there.
Update
Instaed of fixnig the issue I found this workaround.
https://fsprojects.github.io/FSharp.Configuration/
I don't get the purpose of ConnectionStringOrName if you have to supply the connection string anyway. Also why do you have to specify it twice. Makes very little sense to me :(
When using type providers, you often need two separate data sources:
Compile-time one that is used when you are editing the code and compiling the code. The type provider uses this connection or data source to infer the schema of the data - in case of SQL provider, this is connection to the database that is used to check that all your column names exist etc.
Run-time one is used when you actually run the program after it is deployed somewhere. This is where you'll read the actual data from.
The reason why you need two is that the run-time data source may be determined at runtime and it may not be accessible at compile-time (you typically have access to a dev database, but not to production database). The compile-time connection needs to be a constant, so that the provider can use it (when compiling your code) without running any part of your code.
In case of the SQL command provider:
type SelectCmd = SqlCommandProvider<"SELECT ...",
ConnectionStringOrName = "name=DefaultConnection",
SingleRow = true,
AllParametersOptional = true>
let cmd = new SelectCmd(??????)
"name=DefaultConnection" tells the provider to use an app.config key at compile-time
????? is where you need to specify the run-time connection string
To read the connection string from app.config, you can use the standard .NET methods like using ConfigurationManager:
open System.Configuration
let conn = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
let cmd = new SelectCmd(conn)
Something like this would not work when passing the connection string to the SqlCommandProvider, because this needs to run some code to read the string and that's only possible at runtime. That's why the SQL command provider has a handy option to specify name=DefaultConnection as a special string.

Migrate EAP5 to JBoss7 - remote invocation error

Hi this is my scenario,
I am trying to migrate an app from JBoss5 to JBoss7.
I am using jboss-as-7.1.1.Final.
The error I am getting is:
No EJB receiver available for handling [appName:,modulename:myapp-ejb,distinctname:] combination for invocation context org.jboss.ejb.client.EJBClientInvocationContext#6b9bb4bb
at org.jboss.ejb.client.EJBClientContext.requireEJBReceiver(EJBClientContext.java:584) [jboss-ejb-client-1.0.5.Final.jar:1.0.5.Final]
at org.jboss.ejb.client.ReceiverInterceptor.handleInvocation(ReceiverInterceptor.java:119) [jboss-ejb-client-1.0.5.Final.jar:1.0.5.Final]
at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:181) [jboss-ejb-client-1.0.5.Final.jar:1.0.5.Final]
at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:136) [jboss-ejb-client-1.0.5.Final.jar:1.0.5.Final]
at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:121) [jboss-ejb-client-1.0.5.Final.jar:1.0.5.Final]
at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:104) [jboss-ejb-client-1.0.5.Final.jar:1.0.5.Final]
I have looked at several discussions with the same error message but I just cant figure out what I am doing wrong.
In the deployments directory I have only one myapp.war. I do not deploy a .ear file. I have a dependency (myapp-ejb.jar) deployed as a module.
I have followed the instructions from https://docs.jboss.org/author/display/AS71/How+do+I+migrate+my+application+from+AS5+or+AS6+to+AS7 in section "Migrate EAP 5 Deployed Applications That Make Remote Invocations to AS 7".
SERVER
In the myapp-ejb.jar I have a bunch of JNDI names like:
public static final String ACCOUNT_REMOTE = "ejb:/myapp-ejb//AccountBean!com.company.myapp.ejb.account.AccountRemote";
The lookup is done from the client by invoking this static method which is defined in myapp-ejb.jar:
public static AccountRemote getAccountRemote() throws NamingException {
if (accountRemote == null){
InitialContext ic = new InitialContext();
Object ref = ic.lookup(JNDINames.ACCOUNT_REMOTE);
accountRemote = (AccountRemote) PortableRemoteObject.narrow(ref, AccountRemote.class);
}
return accountRemote;
}
All remote interfaces are for stateless EJB like:
#Stateless
#Remote(AccountRemote.class)
public class AccountBean implements AccountRemote {
CLIENT
From the myapp.war I make a remote invocation to the myapp-ejb.jar using the above static method getAccountRemote().
In the myapp.war/WEB-INF directory I have added a jndi.properties and a jboss-ejb-client.properties.
The jndi.properties contains only one value:
java.naming.factory.url.pkgs=org.jboss.ejb.client.naming
The jboss-ejb-client.properties contains:
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=default
remote.connection.default.host=localhost
remote.connection.default.port=4447
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
I have removed the security realm on remoting from the standalone.xml:
<subsystem xmlns="urn:jboss:domain:remoting:1.1">
<connector name="remoting-connector" socket-binding="remoting" />
</subsystem>
I have added the JBOSS_HOME/bin/client/jboss-client.jar to the myapp.war/WEB-INF/lib.
The application deploys successfully without any errors but when I launch localhost:8080/ I get the No EJB receiver available for handling error.
Does anyone knows what I have missed? Any suggestions?
"EJB client API approach" for remote EJB invocation from one node to another node in clustered JBOSS:
------------------------------------------------------------------------------------
1. To call EJB from remote location we need to enable "remoting-ejb-receiver" on server side.
Please refer to “standalone_changes.xml” to know change details.
2. Also we need to register the "remoting-ejb-receiver" to the application, so that the application can receive remote EJB.
Please refer to “jboss-ejb-client.xml” section.
3. Now we need to call remote EJB in "EJB client API approach" way, which needs to have JNDI name pattern as:
ejb:<app-name>/<module-name>/<distinct-name>/<bean-name>!<fullclassname-of-the-remote-interface>
In our case it will be: ejb:myapp-ejb//node1/AccountBean!com.company.myapp.ejb.account.AccountRemote
Important to note that identification to remote location IP address is not based on InitialContext as InitialContext will not contain any IP address as normally happens with "remote://URL:Port".
The remote location identification is based on <distinct-name> passed in JNDI. JBOSS will internally identify the remote IP based on <distinct-name>.
Hence is required to provide unique <distinct-name> to the application running on different nodes.
Add "<distinct-name>${jboss.node.name}</distinct-name>" to “jboss-app.xml”. Make sure that jboss.node.name property is always unique.
But then jboss.node.name should be added as environmental property while server startup.
For test purpose we can provide hardcoded value like:
For node1: "<distinct-name>node1</distinct-name>" to “jboss-app.xml”.
For node2: "<distinct-name>node2</distinct-name>" to “jboss-app.xml”.
standalone_changes.xml:
------------------------------------------------------------------------------------
<subsystem xmlns="urn:jboss:domain:remoting:1.1">
<outbound-connections>
<remote-outbound-connection name="remote-ejb-connection-host2" outbound-socket-binding-ref="remote-ejb-host2" username="xxx" security-realm="ejb-security-realm">
<properties>
<property name="SASL_POLICY_NOANONYMOUS" value="false"/>
<property name="SSL_ENABLED" value="false"/>
</properties>
</remote-outbound-connection>
...........
...........
</outbound-connections>
</subsystem>
...........
...........
<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
<outbound-socket-binding name="remote-ejb-host2">
<remote-destination host="${jboss.ejb.host2}" port="${jboss.ejb.host2.port}"/>
</outbound-socket-binding>
...........
...........
</socket-binding-group>
...........
...........
<management>
<security-realms>
<security-realm name="ejb-security-realm">
<server-identities>
<secret value="${jboss.ejb.remoting.password}"/>
</server-identities>
</security-realm>
...........
...........
</security-realms>
</management>
jboss-app.xml:
------------------------------------------------------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
<jboss-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee">
<distinct-name>node1</distinct-name>
<security-domain>xyz</security-domain>
<unauthenticated-principal>guest</unauthenticated-principal>
<library-directory>lib</library-directory>
</jboss-app>
jboss-ejb-client.xml
------------------------------------------------------------------------------------
<jboss-ejb-client xmlns="urn:jboss:ejb-client:1.0">
<client-context>
<ejb-receivers>
<remoting-ejb-receiver outbound-connection-ref="remote-ejb-connection-host2"/>
<!-- <remoting-ejb-receiver outbound-connection-ref="${jboss.remote.outbound.connection.host3}"/> -->
</ejb-receivers>
</client-context>
</jboss-ejb-client>
For more details refer to:
"https://docs.jboss.org/author/display/AS71/Remote+EJB+invocations+via+JNDI+-+EJB+client+API+or+remote-naming+project" which tells us different way of remote EJB location.
You don't actually require jboss-client.jar if you are using JBOSS as your App server. Please add the following property to your initialContext or jndi.propeties file everything would be fine.
jboss.naming.client.ejb.context=true
also please remove the property unless you are calling from a standalone client or server other than Jboss.
java.naming.factory.url.pkgs=org.jboss.ejb.client.naming
Try with these settings.

Fitnesse Slim query test fails while trying to access linq datacontext

I wrote a query that gets a list of objects using linq. The code executes fine in the project, but fails when I try to access it from the fitnesse project.
base(global::System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString, mappingSource)
I guess it has something to do with the connection string, but I don't know how to specify the connection string separately for the fitnesse project. Both project and fitnesse project are part of the same solution.
Any ideas?
Thanks,
Jenny
You need to specify where to find the app config file:
http://www.syterra.com/Slim/AppConfigFiles.html
Thanks, I already tried adding a suite.config and then app config to my c:\fitnesse folder - where the .jar file is.
I added -c option c:\Fitnesse\suite.config to the command section on the test page.
Here's the suite.config file:
c:\fitnesse\myapp.config
^.svn$
Here's the myapp.config file:
The test still fails here:
public MyDataContext() :
base(global::System.Configuration.ConfigurationManager.ConnectionStrings["mycon"].ConnectionString, mappingSource)
{
OnCreated();
}

Database error ASP.NET

I have my projects setup as follows (repository pattern):
myProj.Data (Contains the xDB.mdf) [Library]
myProj.Service (Uses myProj.Data) [Library]
myProj.WebApp (Uses myProj.Service) [ASP.NET Website]
In 1. I access my Database via Linq to Sql. The app.config looks like this:
<add name="XDbConnectionString" connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\XDb.mdf;Integrated Security=True;User Instance=True" providerName="System.Data.SqlClient" />
When I try to retrieve some data via the web, I get this error thrown from the Service Project:
An attempt to attach an auto-named database for file D:\MyProject\XDb.mdf failed. A database with the same name exists, or specified file cannot be opened, or it is located on UNC share.
From this code:
return (from p in repository.GetPostMedia() where p.PostId == postId select p).ToList();
Check in Management Studio that you don't have that database already attached, if so detach it and try again.
I moved the database from the myProj.Data into myProj.Web App_Data folder and it worked.

Resources