I am trying to make a simple REST Service with .NET 4.0 that uses ninject to inject any dependencies for the service.
This is what my service looks like currently:
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class ReportService
{
private readonly ReportManager _reportManager;
public ReportService(ReportManager reportManager)
{
_reportManager = reportManager;
}
[WebInvoke(UriTemplate = "GetReports", Method = "GET")]
public List<ReportDTO> GetReports()
{
var reports = _reportManager.GetReports();
return reports.ToList();
}
}
This is my global.asax:
public class Global : NinjectHttpApplication
{
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes();
}
private void RegisterRoutes()
{
RouteTable.Routes.Add(new ServiceRoute("ReportService", new NinjectWebServiceHostFactory(), typeof(ReportService)));
}
protected override IKernel CreateKernel()
{
return new StandardKernel(new ServiceModule());
}
}
And my ServiceModule:
public class ServiceModule : NinjectModule
{
public override void Load()
{
Bind<IFRSDbContext>().To<FRSDbContext>().InRequestScope();
Bind<IDatabaseFactory>().To<DatabaseFactory>().InRequestScope();
Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
Bind<IReportRepository>().To<ReportRepository>();
Bind<ReportManager>().ToSelf();
Bind<ReportService>().ToSelf();
}
}
I keep getting the following exception when I try to run my service:
Description: An unhandled exception occurred during the execution of
the current web request. Please review the stack trace for more
information about the error and where it originated in the code.
Exception Details: System.NullReferenceException: Object reference not
set to an instance of an object.
Source Error:
An unhandled exception was generated during the execution of the
current web request. Information regarding the origin and location of
the exception can be identified using the exception stack trace below.
Stack Trace:
[NullReferenceException: Object reference not set to an instance of an object.]
System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers) +222
System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context) +194
System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context) +339
System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +253
[HttpException (0x80004005): Object reference not set to an instance of an object.]
System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +9079228
System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +97
System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +256
EDIT
I've updated to the most current version of my Service.. I am using Ninject 2.3 and Ninject.Extensions.Wcf 2.3 from here but am still having no luck.. what am I doing wrong? I've followed everything from the WcfTimeService example except that I am using a REST service and not a .svc Wcf service...
You shouldn't call Application_Start. Instead override OnApplicationStarted
After downloading the sources of Ninject.Web.Common and Ninject.Extensions.Wcf I was able to track down the issue.
In order to get this to work without a *.svc file you need to call the Application_Start() method of the NinjectHttpApplication at the end of the Application_Start() in Global.asax.cs file, like so:
public class Global : NinjectHttpApplication
{
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes();
Application_Start(); // added call
}
private void RegisterRoutes()
{
RouteTable.Routes.Add(new ServiceRoute("ReportService", new NinjectWebServiceHostFactory(), typeof(ReportService)));
}
protected override IKernel CreateKernel()
{
return new StandardKernel(new ServiceModule());
}
}
Without doing this, the Kernel never gets created and therefore that is what causes the NullReferenceException. After I did this everything started working perfectly.
Related
I'm trying to unit test an api call made with retrofit and rxjava.
In order to do that i'm mocking the api call object but api calls subscriber won't trigger its onNext method.
ApiCallsTest.java:
//custom object replacing api call response object
Observable<FastRechargeClass[]> apiObservable = Observable.just(fastRechargeList);
InterfaceAPI api = mock(InterfaceAPI.class);
when(retrofitApi.getApiInterface(context)).thenReturn(api); when(api.getLatestTransactions("token")).thenReturn(apiObservable);
apiCalls.getLatestTransactions("token",context);
ApiCalls.java:
public void getLatestTransactions(String token, final Context context) {
String methodName = "getLatestTransactions";
InterfaceAPI api = retrofitApi.getApiInterface(context);
Observable<FastRechargeClass[]> call = api.getLatestTransactions(token);
call.observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io()).subscribe(new Observer<FastRechargeClass[]>() {
#Override
public void onSubscribe(Disposable d) {
WriteLog.print("onSubscribe");
}
#Override
public void onNext(FastRechargeClass[] fastRechargeClasses) {
fastRechargeManager.runUpdateFastRechargeDb(fastRechargeClasses);
}
#Override
public void onError(Throwable e) {
logOnFailureRequests(methodName, e.getMessage());
}
#Override
public void onComplete() {
}
});
}
When running test
onSubscribe is being called and it stops
You need to trigger event emission manually. To do this you need to call method
.blockingFirst()
or
.blockingGet()
depends of observable type you are using.
So you have to add
call.blockingGet()
at the end of getLatestTransactions method or this method should return created observable and call blocking get inside a test method.
I expect that uploadImage method finishes once the file is uploaded to AWS, while scanFile method is still running asynchronously in the background;
#RestController
public class EmailController {
#PostMapping("/upload")
#ResponseStatus(HttpStatus.OK)
public void uploadImage(#RequestParam MultipartFile photos) {
awsAPIService.uploadImage(photos);
}
}
...
#Service
public class AwsAPIService {
public void uploadImage(MultipartFile file) {
try {
File fileToUpload = this.convertMultiPartToFile(file);
String fileName = this.generateFileName(file);
s3client.putObject(new PutObjectRequest(AWS_S3_QUARANTINE_BUCKET_NAME,fileName, fileToUpload));
fileToUpload.delete();
// start scan file
scanFile();
} ...
}
#Async
public void scanFile() {
log.info("Start scanning");
String queueUrl = sqs.getQueueUrl("bucket-antivirus").getQueueUrl();
List<Message> messages = sqs.receiveMessage(new ReceiveMessageRequest().withQueueUrl(queueUrl)
.withWaitTimeSeconds(20)).getMessages();
for (Message message : messages) {
// delete message
...
}
}
}
...
#EnableAsync
public class AppConfig {
#Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setMaxPoolSize(2);
taskExecutor.setQueueCapacity(200);
taskExecutor.afterPropertiesSet();
return taskExecutor;
}
}
But this seems still running synchronously. What is the problem here?
By default #Async and other Spring method-level annotations like #Transactional work only on the external, bean-to-bean method call. An internal method call from uploadImage() to scanFile() in the same bean won't trigger the proxy implementing the Spring behaviour. As per Spring docs:
In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation, in effect, a method within the target object calling another method of the target object, will not lead to an actual transaction at runtime even if the invoked method is marked with #Transactional. Also, the proxy must be fully initialized to provide the expected behaviour so you should not rely on this feature in your initialization code, i.e. #PostConstruct.
You could configure AspectJ to enable annotations on internal method calls, but it's usually easier to refactor the code.
I am testing this code.
service.getProducts()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Result<Catalog<SoajsProductPreview>>>() {
#Override
public void onError(Throwable e) {
view.showErrorView(e);
}
#Override
public void onNext(Result<Product> products) {
view.showProducts(products)
}
#Override
public void onCompleted() {}
});
Testing that view.showProducts() the mocked service returns results works fine.
I do
when(service.getProducts().thenReturn(someObservable);
Now I want to test that view.ShowErrorView() is called when the service throws an error but I can't find a way to do that:
Obviously the following doesn't compile
when(service.getProducts().thenReturn(someException);
And this throws an exception immediately but doesn't call the Subscriber's onError method
when(service.getProducts().thenReturn(someException);
How can I get Subscriber.onError() called?
when(service.getProducts().thenReturn(Observable.error(someException))
should work. See the documentation starting here.
I am trying to create unit test with scout context and I can't find proper tutorial or example for it.
When I create test with ScoutClientTestRunner, I get error
java.lang.Exception: Client session class is not set. Either set the default client session using 'ScoutClientTestRunner.setDefaultClientSessionClass' or annotate your test class and/or method with 'ClientTest'
I try to set client session class like this :
#Before
public void setClassSession() throws Exception {
ScoutClientTestRunner.setDefaultClientSessionClass(ClientSession.class)
}
and
#BeforeClass
public void setClassSession() throws Exception {
ScoutClientTestRunner.setDefaultClientSessionClass(ClientSession.class);
}
I try to add #ClientTest to the class and to all methods but I still get same error.
How to set client session in tests if you use ScoutClientTestRunner ?
The ScoutClientTestRunner ensures that the JUnit tests are executed having all the Scout Context (OSGi and so on) available.
Your attempts with #Before or #BeforeClass are too late. You need to provide the Scout Context initialization parameters before that. As the exception message says, you have 2 possibilities:
(1) #ClientTest annotation
You can annotate test classes or methods with #ClientTest using the clientSessionClass parameter:
#RunWith(ScoutClientTestRunner.class)
#ClientTest(clientSessionClass = ClientSession.class)
public class DesktopFormTest {
#Test
public void test1() throws Exception {
//Do something requiring a scout context:
//for example instantiate a DesktopForm.
}
}
If necessary you can also do it at method level:
#RunWith(ScoutClientTestRunner.class)
public class DesktopFormTest {
#Test
#ClientTest(clientSessionClass = Client1Session.class)
public void test1() throws Exception {
//client session is an instance of Client1Session.
}
#Test
#ClientTest(clientSessionClass = Client2Session.class)
public void test2() throws Exception {
//client session is an instance of Client2Session.
}
}
(2) Defining a TestEnvironment
When the test is run (directly or using maven-tycho), a lookup for a fully qualified class org.eclipse.scout.testing.client.runner.CustomClientTestEnvironment is done.
The CustomClientTestEnvironment class should implement org.eclipse.scout.testing.client.runner.IClientTestEnvironment
The method setupGlobalEnvironment() is called once and can be used to define the default client session with ScoutClientTestRunner.setDefaultClientSessionClass(..). This method can also be used to register required services.
Here an example:
package org.eclipse.scout.testing.client.runner; // <= can not be changed.
// add imports
public class CustomClientTestEnvironment implements IClientTestEnvironment {
#Override
public void setupGlobalEnvironment() {
//Set client session:
ScoutClientTestRunner.setDefaultClientSessionClass(ClientSession.class);
}
#Override
public void setupInstanceEnvironment() {
}
}
Of course (1) and (2) are compatible. The second mechanism defines only the default and ClientSession configured with (1) will override the default.
I am coding my first ui test using holoEverywhere, I want to test a Activity which extends from org.holoeverywhere.app.Activity and I have this problem...
I tried to in the target app manifest this
And also in the manifest of the unit test project.
java.lang.IllegalStateException: Application instance isn't HoloEverywhere. Please sure that you extend class
android.test.mock.MockApplication from a
org.holoeverywhere.app.Application at
android.support.v4.app._HoloActivity.onInit(_HoloActivity.java:449) at
android.support.v4.app._HoloActivity.forceInit(_HoloActivity.java:207)
at org.holoeverywhere.app.Activity.onCreate(Activity.java:227) ......
This is my code:
public class MainActivityUnitTest extends
android.test.ActivityUnitTestCase<MainActivity> {
private MainActivity activity;
public MainActivityUnitTest () {
super(MainActivity.class);
}
#Override
protected void setUp() throws Exception {
super.setUp();
Context context = getInstrumentation().getTargetContext();
Intent intent = new Intent(context,
MainActivity.class);
startActivity(intent, null, null);
activity = getActivity();
}
The problem is your mock application (which is created by the unit test) is not a HoloEverywhere application. Call setApplication before calling startActivity. This will replace the used android.test.mock.MockApplication with an org.HoloEverywhere.app.Application.
#Override
protected void setUp() throws Exception
{
super.setUp();
setApplication(new org.HoloEverywhere.app.Application());
Intent intent = new Intent(getInstrumentation().getTargetContext(), DeclarerenActivity.class);
startActivity(intent, null, null);
}