Unnecessary null check in mapstruct - code-coverage

I'm using mapstruct in my project, and recently went to add some 'mutation analysis' using pitest.
The problem I have is that a mutant is created on some generated code, and I cannot fix my test to kill it since this is concerning null check generated by mapstruct, that are unreacheable.
ie, if I have the following mapper :
#Mapper
public abstract class MyMapper {
#Mapping(source= "someInnerObject.field", target="someField")
public abstract Bar toBar(Foo foo);
}
Mapstruck will generate something like this :
public class MyMapperImpl extends MyMapper {
#Override
public Bar toBar(Foo foo) {
if(foo == null) {
return null; // reacheable code, all is fine here.
}
Bar bar = new Bar();
bar.setSomeField(fooSomeField(foo))
return bar;
}
private String fooSomeField(Foo foo) {
if (foo == null) {
return null; // Unreacheable code, already tested in public method.
}
SomeInnerObject innerObject = foo.getSomeInnerObject()
if(innerObject == null) {
return null; // reacheable code, no problem here
}
String field = o.getField();
if(field == null) {
return null; // reacheable, no problem here.
}
return field;
}
}
As we can see, mapstruct generates a null check that is unreacheable, making it impossible to cover those line in test. The mutation analyser tries to return "" instead of null on the unreacheable line, and therefore, the mutant is never detected by my tests. This leads makes it impossible to get 100% code coverage and 100% mutation coverage.
I don't think excluding this generated code from the coverage or the mutation analysis would be a good choice, since the generated code reflect behavior that is coded as annotations in the mapper : So we would like to make sure these behaviors are correctly covered in tests.
Do someone here had the same problem, or any suggestion ?
I tried many different mapper config to get rid of the unreacheable line without success (unless I just disable all null checks, which would change my application logic).

The way MapStruct generates code doesn't allow us to skip the null check in the private method.
You can try raising an issue in the MapStruct project. However, I am not sure that it is worth spending time on skipping this null check. The JIT will in any case remove that check during runtime.
The topic about 100% code coverage and 100% mutation coverage is a topic for discussion that will lead to closing this question.

Related

Xtext CustomScopeProvider Problems with adding candidates

I am working on an xtext Project where I have to customize the Scope Provider. I need to add up some possible candidates for the scope. The first part (getServiceInputs()) works fine but for the second one (addAll(sub.GetSubRecipeParameters()) not. Debugging showed that they get removed from its original source (sub) and can therefore not be retrieved again. When simply commenting out the addAll line the SubRecipeParameters remain in sub. Really dont know how to solve that, tried already some work arounds. Anyone with an Idea?
public class AutomationServiceDslScopeProvider extends AbstractAutomationServiceDslScopeProvider {
#Override
public IScope getScope(EObject context, EReference reference) {
if (context instanceof ServiceInvocationParameter
&& reference == AutomationServiceDslPackage.Literals.LITERAL) {
ServiceInvocation serviceCall = (ServiceInvocation) invocationParameter.eContainer();
ServiceDefinition calledService = serviceCall.getService();
List<ServiceParameterDefinition> candidates= calledService.getServiceInputs();
final EObject rootContainer = EcoreUtil.getRootContainer(context);
List<SubRecipeDefinition> subs = EcoreUtil2.getAllContentsOfType(rootContainer, SubRecipeDefinition.class);
for(SubRecipeDefinition sub:subs) {
for(RecipeStep step:sub.getRecipeSteps()) {
if(step.getName()==serviceCall.getName()) {
candidates.addAll(sub.getSubRecipeParameters());
}
}
}
return Scopes.scopeFor(candidates);
Thanks for any help!!
This is normal EMF behaviour if you move elements from one EList to another one. The solution is to create a new list e.g. new ArrayList<>() and also add the inputs there
List<ServiceParameterDefinition> candidates = new ArrayList<>();
candidates.addAll(calledService.getServiceInputs());

Ok() vs Ok(null)

What's the difference between Ok() vs Ok(null)?
The Ok(null) returns status code 204 with no body but header, therefore we have to change our code in this way:
[HttpGet]
public IActionResult GetTest(string test)
{
MyClass result = GetMyClass(test)
if(result == null) return Ok();
return Ok(result);
}
I suggest you use NoContent (HttpStatus 204).
That means the request successfully executed, but didn't return a value or object, and it's an official status code for this purpose
See the following example:
[HttpGet()]
public IActionResult GetTest(string test)
{
var result = GetMyClass(test)
return result != null
? Ok(result)
: NoContent();
}
Hope you'll find this useful.
Official documentation says
Ok() Creates a OkResult object that produces an empty Status200OK
response.
Ok(Object) Creates an OkObjectResult object that produces an
Status200OK response.
https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.controllerbase.ok?view=aspnetcore-2.1
When you pass null , it will creates an OkObjectResult of null , So you are getting 204 status code.
HTTP status code 204 is a valid "success" result that lets the recipient know that there is no content. This actually seems rather appropriate, but still it may not be supported everywhere.
Either your could 'teach' (or program) your recipient to handle it correctly, or you need to apply your workaround.
If you need this workaround in multiple places then you could use a base class to overload Ok() (or more precisely, redefine it) to always do what you need, like this:
public abstract class MyBaseApiController : ApiController
{
public new IHttpActionResult Ok<T>(T content)
{
if (content == null) return base.Ok();
return base.Ok(content);
}
}

Implementing ASP.NET MVC error handling using Castle Windsor's Dynamic Proxies

I spent a long time trying to get the ASP.NET MVC [HandleError] attribute to work in my websites. It seemed like a good idea to go with the solution offered by the framework, but I just couldn't get it to do anything useful. Then I tried writing my own attribute (mainly so that I could step in to the code with the debugger), but although my code seemed to be doing all the right things, after it executed the framework took over and did mysterious things. Finally I tried the MVC Contrib's [Rescue] attribute, which was better but I still couldn't get it to do what I wanted.
One problem is that exceptions thrown in code embedded in aspx / ascx pages get wrapped in HttpException's and WebHttpException's.
Another problem for me was that the system is very opaque. I was essentially poking inputs in to a black box with some desired outputs in mind, but with no idea (other than the documentation, which doesn't seem very accurate / thorough) what the relationship was between them.
So, what to do?
I went for Dynamic Proxies in Castle Windsor, using the code below, which tries to handle Database errors, for which I have a specific Exception (AccessDBException).
The _alreadyAttemptedToShowErrorPage is to stop infinite recursion in the case where the error page throws an Exception.
The GetAccessDBException(...) method finds the relevant exception anywhere in the Exception stack, for the case when there are problems in aspx / ascx code.
The code requires that there is a BaseController class that all controllers derive from. This class is used to add a CreateErrorView(...) method (being as the standard View(...) method is protected)
public class AccessDBExceptionHandlingDynamicProxy : IInterceptor
{
private bool _alreadyAttemptedToShowErrorPage;
public AccessDBExceptionHandlingDynamicProxy()
{
_alreadyAttemptedToShowErrorPage = false;
}
public void Intercept(IInvocation invocation)
{
Contract.Requires(invocation.Proxy is BaseController);
try
{
invocation.Proceed();
}
catch (HttpException e)
{
if (_alreadyAttemptedToShowErrorPage == true) throw e;
_alreadyAttemptedToShowErrorPage = true;
var dbException = GetAccessDBException(e);
if (dbException != null)
{
var baseController = (invocation.Proxy as BaseController);
var view = baseController.CreateErrorView("AccessDBException", new AccessDBExceptionViewModel(dbException));
baseController.Response.Clear();
baseController.Response.StatusCode = (int) HttpStatusCode.InternalServerError;
view.ExecuteResult(baseController.ControllerContext);
baseController.Response.End();
}
else
{
throw e;
}
}
}
private static AccessDBException GetAccessDBException(HttpException e)
{
AccessDBException dbException = null;
Exception current = e;
while (dbException == null && current != null)
{
if (current is AccessDBException) dbException = (current as AccessDBException);
current = current.InnerException;
}
return dbException;
}
}

Use MiniProfiler only for debugging or local request

I would like to use the MiniProfiler for my MVC3 application, so I followed Scott Hanselman's blog post
My Global.asax.cs file has the necessary changes like in the source's MVC sample.
But I would like to measure a particular call in my controller.
So I put this code in controller:
if (Request.IsLocal)
{
var profiler = MiniProfiler.Current;
using (profiler.Step("SelectUserDetail Function"))
{
user = UserService.SelectUserDetail(userId);
}
}
I suspect my code will never in production environment as I'm wrapping this block in a Request.IsLocal check.
How can I do this check for only for local call or if I run in debug mode? At any case, it should execute the user = UserService.SelectUserDetail(userId) statement.
If I understand your question correctly, you're only wanting to call MiniProfiler's .Step() extension method when running locally (or debugging), correct?
If so, this kinda defeats the purpose of MiniProfiler, which is to have all this instrumentation available for production code, without impacting production.
I'm confident you can simply do this in your code:
using (MiniProfiler.Current.Step("SelectUserDetail Function"))
{
user = UserService.SelectUserDetail(userId);
}
and it will have virtually no impact on your app; we literally do this hundreds of times in our code here on Stack Overflow without issue (as well as every single database query).
You should only need to have your checks when a new request comes in:
protected void Application_BeginRequest()
{
if (Request.IsLocal) { MiniProfiler.Start(); }
}
When you're running in production, any calls to MiniProfiler.Current.Step() will return nothing, since the profiler is null (the beauty of extension methods).
If you still want to prevent any using statements from appearing in your production code, you should familiarize yourself with preprocessor directives. See this question, as well. However, I would strongly advise against them for this purpose, as it isn't necessary.
I usually create something like DebugHelper static class and define there:
public static class DebugHelper
{
private static bool? _isDebugEnabled = false;
public static bool IsDebug
{
get
{
if (!_isDebugEnabled.HasValue)
{
_isDebugEnabled = false;
#if DEBUG
_isDebugEnabled = true;
#endif
}
//may be extra rules like check for some debug key in HttpContext.Current etc.
return _isDebugEnabled.Value;
}
set { _isDebugEnabled = value; }
}
public static bool IsDevEnvironment
{
get
{
string environment = settingsService.GetSettingByKey<string>("environment");
return environment == "dev";
}
}
public static bool IsTestEnvironment
{
get
{
string environment = settingsService.GetSettingByKey<string>("environment");
return environment == "test";
}
}
DebuHelper allows me easily switch on/switch off debug mode, logging, tracing etc. add extra output or whatever for dev and test environment

Access the website settings of an asp.net mvc app stored in a database table using NHibernate

I have an ASP.NET MVC app which depends on a lot of settings (name-value pairs), I am planning to store this information in a database table called SiteSettings. Is there an easy way in which I can get these settings using NHibernate. And what are the best practices when saving settings for a web application. And by settings I mean the settings which control the flow of processes in the web application and which are governed by business rules. These are not the typical connection string kind of settings. I was unable to get much information on the web on this topic. Maybe I am not searching on the right keywords, Any help will be greatly appreciated.
I can't answer in the context of nhibernate (which I'm not using) or best practices (I came up with this on my own recently). However, it works well for me, and will probably work for you.
I have a table (Biz_Config) in the database to store business preferences. (I've created a web.config section for what I call IT preferences.)
I have a class that is in charge of managing the biz preferences. The constructor grabs the entire table (one row per setting) and copies these into a dictionary, and it has methods to access (such as bizconfig.get("key")) and update this dictionary, also updating the table at the same time. It also has a few shortcut properties for specific dictionary values, especially where the value has to be cast (I have a few important numbers). It works quite well.
In order to be more efficient and not instantiate it every time I need a setting, and also to access it easily from my controllers and views, I created a static class, Globals, that is in charge of getting things out of the session or application variables. For the biz config object, it checks the application variable and, if null, creates a new one. Otherwise it just returns it. Globals is part of my helpers namespace, which is included in my web.config to be available to my views. So I can easily call:
<% Globals.Biz_Config.Get("key") %>
I hope this helps. If you'd like code, I can dig that up for you.
James
If you have a set of key/value pairs, you probably want to use a <map>. See the official NHibernate documentation or Ayende's post about 'NHibernate Mapping - <map/>'.
I have come up with a solution which is quite similar to the one suggested by James. I have an SiteSettingsService class which manages the settings for the whole site, it has a simple dependency on an interface called ISiteServiceRepository. This might not be the most elegant solution, But it is working perfectly for me. I have also configured the SiteSettingsService class as a Singleton using StructureMap. So, it saves me unnecessary instantiantion every time I need any settings.
//ISiteServiceRepository, an implementation of this uses NHibernate to do just two things
//i)Get all the settings, ii)Persist all the settings
using System.Collections.Generic;
using Cosmicvent.Mcwa.Core.Domain.Model;
namespace Cosmicvent.Mcwa.Core.Domain {
public interface ISiteServiceRepository {
IList<Setting> GetSettings();
void PersistSettings(IDictionary<string, string> settings);
}
}
//The main SiteSettingsService class depends on the ISiteServiceRepository
using System;
using System.Collections.Generic;
using Cosmicvent.Mcwa.Core.Domain;
using Cosmicvent.Mcwa.Core.Domain.Model;
namespace Cosmicvent.Mcwa.Core.Services {
public class SiteSettingsService : ISiteSettingsService {
private readonly ISiteServiceRepository _siteServiceRepository;
private IDictionary<string, string> _settings;
public SiteSettingsService(ISiteServiceRepository siteServiceRepository) {
_siteServiceRepository = siteServiceRepository;
//Fill up the settings
HydrateSettings();
}
public int ActiveDegreeId {
get {
return int.Parse(GetValue("Active_Degree_Id"));
}
}
public string SiteTitle {
get { return GetValue("Site_Title"); }
}
public decimal CounsellingFee {
get { return decimal.Parse(GetValue("Counselling_Fee")); }
}
public decimal TuitionFee {
get { return decimal.Parse(GetValue("Tuition_Fee")); }
}
public decimal RegistrationFee {
get { return decimal.Parse(GetValue("Registration_Fee")); }
}
public void UpdateSetting(string setting, string value) {
if (!string.IsNullOrEmpty(setting) && !string.IsNullOrEmpty(value)) {
SetValue(setting, value);
PersistSettings();
}
}
//Helper methods
private void HydrateSettings() {
_settings = new Dictionary<string, string>();
IList<Setting> siteRepoSettings = _siteServiceRepository.GetSettings();
if (siteRepoSettings == null) {
throw new ArgumentException("Site Settings Repository returned a null dictionary");
}
foreach (Setting setting in siteRepoSettings) {
_settings.Add(setting.Name.ToUpper(), setting.Value);
}
}
private string GetValue(string key) {
key = key.ToUpper();
if (_settings == null) {
throw new NullReferenceException("The Site Settings object is Null");
}
if (!_settings.ContainsKey(key)) {
throw new KeyNotFoundException(string.Format("The site setting {0} was not found", key));
}
return _settings[key];
}
private void SetValue(string key, string value) {
key = key.ToUpper();
if (_settings == null) {
throw new NullReferenceException("The Site Settings object is Null");
}
if (!_settings.ContainsKey(key)) {
throw new KeyNotFoundException(string.Format("The site setting {0} was not found", key));
}
_settings[key] = value;
}
private void PersistSettings() {
_siteServiceRepository.PersistSettings(_settings);
}
}
}
Hope this helps future developers facing similar problems. Any suggestions for improving this are more than welcome.

Resources