I have a class defined in a class library like so:
Classlib1 - Client
public class client{
[Required]
public string Firstname {get; set;}
...
[RegularExpression(#"^(?:\d{9}|\d{3}-\d{2}-\d{4}|)$")]
public string SocialSecurityNumber {get; set;}
}
I also have a Test library where I want to ensure that my RegularExpression Attribute Validation is working.
Testlib
[TestMethod]
public void ThrowAnErrorOnSSNWithTooManyDigits(){
var client = new Client(){
Firstname = "Mickey",
...
SocialSecurityNumber = "1234567890123"
};
var vResults = new List<ValidationResult>();
var context = new ValidationContext(client){MemberName = "SocialSecurityNumber"};
var result = Validator.TryValidateProperty(client.SocialSecurityNumber, context, vResults);
Assert.IsFalse(result)
}
However, my Assertion always fails because result always equals true. I tried changing my validator to validate a required firstname instead of SocialSecurityNumber thinking that my RegEx wasn't quite right -- however, that returns true as well -- even if I set Firstname = ""
What do I need to do to get the Validator working in my Test classlib?
So, In combing through my project once again, I realized that the Test project that I added was actually targeting .Net4.6 while the rest of my projects are all targeting .Net Core 2.0.
I added a new .NetCore Test project and copied all my tests in there and everything worked as expected.
Related
Is it possible to implement Pattern querying with JPA Criteria API?
In my case, regex patterns are stored into a quick bag property; and I'm trying to avoid using native queries (e.g. PostgreSQL POSIX support).
#Entity #Table(name = "rcp")
public class Recipient {
#Id #Column(name = "rcp_email_id")
#Email
private String email;
#CollectionTable(joinColumns = #JoinColumn(name = "rcp_email_fk"))
#ElementCollection(fetch = EAGER)
#Convert(converter = PatternConverter.class)
private Set<Pattern> rules = new HashSet<>();
...
}
So I figured I could use the Criteria API but failed to properly develop the technlogy, obviously:
#AllArgsConstructor
public class RecipientSpecification implements Specification<Recipient> {
private String sample;
#Override
public Predicate toPredicate(Root<Recipient> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
return builder.exists(root.join("rules").as(Pattern.class).matcher(sample).find());
}
}
I thought I could work on the join with a cast and execute the Java Pattern logic by casting the properties, which I realize to be dumb now because it has no sense from the JPA DSL point of view. It doesn't even compile! But is there a proper way to proceed?
Thanks in advance
I'm creating tests, and every time I need to update a simple object, I create tests that check if all properties that I will pass through the method are changed.
For instance:
public class User {
public string name { get; private set }
public string email { get; private set }
public string password { get; private set }
public void UpdateData(string name, string email, string password){
//update fields
}
}
Test class:
[TestMethod]
public void Should_Update_Data(){
var arrange = {
name: "NewName",
Email: "NewEmail#Something.com",
Password: "123456"
}
var user = new User();
user.UpdateData(arrange.name, arrange.Email, arrange.Password);
//Assert user.name equals arrange.name
//Assert user.email equals arrange.email
//Assert user.password equals arrange.password
}
But I'm confused if it's a good practice to do so many asserts, and it's very boring to check all properties that I'm updating were really updated...
I don't think it's necessarily bad practice to do many asserts but there are definitely benefits to keeping tests to perform a single assert:
tests stay more focused
easier to understand what is being tested
assertions won't mask other assertions, ie if user.name assertion fails then user.email will never get executed, which results in longer feedback cycles
What sorts of regressions are you trying to prevent from happening with your tests? Is it effective in detecting those regressions from happening? Does the compiler protect you in the same way?
The contract for updateData is to perform an update on those elements. Therefore, you need to test it. However, you need not explicitly test it. If another part of your test covers the updateData portion, you can rely on that coverage as an implict test.
I suppose your actual method does something more than just set some properties. If not, I would not test these methods as it's too trivial for testing.
In case it is more complicated you will need some unit tests. As for your issue with the various asserts in a single method, I tend to set up my tests a bit differently so that the asserts are separated.
I'd set up and execute the code in the initialize method and then arrange the asserts in separate methods:
[TestClass]
public class UpdatingData
{
User user;
dyanmic arrange = {
Name: "NewName",
Email: "NewEmail#Something.com",
Password: "123456"
};
[TestInitialize]
public void Because(){
user = new User();
user.UpdateData(arrange.Name, arrange.Email, arrange.Password);
//Assert user.name equals arrange.name
//Assert user.email equals arrange.email
//Assert user.password equals arrange.password
}
[TestMethod]
public void UpdatesTheName() => Assert.Equals(user.Name, arrange.Name);
[TestMethod]
public void UpdatesTheEmail() => Assert.Equals(user.Email, arrange.Email);
[TestMethod]
public void UpdatesThePassword() => Assert.Equals(user.Password, arrange.Password);
}
My REST API generates a password on a POST request and stores it in a DB. For development purpose, I'd like to put it in the response, when a development.mode flag is set to true in the application.properties file.
I would like to test this controller and check that if the flag is true, the password is in the response, if false the password is not.
I would like to know if and how I can dynamically set this property value from each test method.
This is my controller:
#RestController
public class PasswordController {
#Value("${development.mode}")
private boolean isDevelopmentMode;
#RequestMapping(value = "/new", method = RequestMethod.POST)
public ResponseEntity<String> generatePassword(#RequestParam(USERNAME_PARAM) String username) {
String password = manager.generatePassword();
String body = "";
if (isDevelopmentMode) {
body = "New password: " + password;
}
return new ResponseEntity<>(body, HttpStatus.OK);
}
}
I have seen documentation to define different property files for testing, using #PropertySource, but it's at the class level and I would like to avoid creating a different file just to change a flag.
I've also seen posts saying you can use ReflectionUtils.setField to change the value of a private field, but for this I have to explicity instantiate my controller and consequently have some issues with Autowired fields. I've tried this:
#RunWith(SpringRunner.class)
#WebMvcTest(PasswordControllerTest.class)
public class PasswordControllerTest extends OtpTest {
#Autowired
private MockMvc mockMvc;
#Test
public void newRoute_developmentModeIsFalse_responseBodyIsEmpty() throws Exception {
PasswordController controller = new PasswordController();
ReflectionTestUtils.setField(controller, "isDevelopmentMode", false);
MockMvc mvc = MockMvcBuilders.standaloneSetup(new PasswordController()).build();
given(manager.generatePassword(any(String.class))).willReturn("123456");
mvc.perform(post("/new").param(PasswordController.USERNAME_PARAM, "test_user")).andExpect(status().isOk()).andExpect(content().string(""));
}
}
Is there a possibility to set the value of a #Value field in each test method? Should I refactor my code to access it differently?
SOLUTION
Thanks to Borys Zibrov it works with this code:
#RunWith(SpringRunner.class)
#WebMvcTest(PasswordController.class)
public class PasswordControllerTest extends OtpTest {
#Autowired
private MockMvc mockMvc;
#Autowired
private WebApplicationContext applicationContext;
#Test
public void newRoute_developmentModeIsTrue_passwordIsInTheResponseBody() throws Exception {
PasswordController controller = applicationContext.getBean(PasswordController.class);
ReflectionTestUtils.setField(controller, "isDevelopmentMode", true);
given(manager.generatePassword(any(String.class))).willReturn("123456");
mockMvc.perform(post("/new").param(PasswordController.USERNAME_PARAM, "test_user")).andExpect(status().isOk())
.andExpect(content().string("New password: 123456"));
}
}
Getting my controller bean from the application context didn't work at first because in my previous code I was using my test class in WebMvcTest annotation.
You could create another applicationContext-tests.xml, connect it to your test via:
#RunWith(SpringRunner.class)
#WebMvcTest(PasswordControllerTest.class)
#ContextHierarchy({
#ContextConfiguration(locations = "path_to applicationContext-tests.xml")
})
public class PasswordControllerTest extends OtpTest {
and override that property development.mode there.
You could also stick to using ReflectionTestUtils but instead of a direct instantiation use a bean from applicationContext constructed by spring for you, and then set a property on that bean.
Or you could just provide a setter for that field.
Could someone explain what is wrong with this and is there a workaround?
private static final String parentField = AbstractType_.parent.getName();
#OneToMany(fetch = FetchType.EAGER, orphanRemoval = true, mappedBy = parentField)
private List<AbstractType> children = new ArrayList<AbstractType>();
In eclipse, this shows and error on the #OneToMany line:
While this would be fine:
The value for annotation attribute OneToMany.mappedBy must be a constant expression.
Also the Maven build fails because of this.
Then again, this will work fine.
private static final String test = "";
#OneToMany(fetch = FetchType.EAGER, orphanRemoval = true, mappedBy = test)
private List<AbstractType> children = new ArrayList<AbstractType>();
UPDATE:
What is happening here, that I wish to get the field name via metamodel, but one can not refer to it at 'mappedBy' attribute.
We manage several ASP.NET MVC client web sites, which all use a data annotation like the following to validate customer email addresses (I haven't included the regex here, for readability):
[Required(ErrorMessage="Email is required")]
[RegularExpression(#"MYREGEX", ErrorMessage = "Email address is not valid")]
public string Email { get; set; }
What I would like to do is to centralise this regular expression, so that if we make a change to it, all of the sites immediately pick it up and we don't have to manually change it in each one.
The problem is that the regex argument of the data annotation must be a constant, so I cannot assign a value I've retrieved from a config file or database at runtime (which was my first thought).
Can anyone help me with a clever solution to this—or failing that, an alternative approach which will work to achieve the same goal? Or does this just require us to write a specialist custom validation attribute which will accept non-constant values?
The easiest way is to write a custom ValidationAttribute that inherits from RegularExpressionAttribute, so something like:
public class EmailAttribute : RegularExpressionAttribute
{
public EmailAttribute()
: base(GetRegex())
{ }
private static string GetRegex()
{
// TODO: Go off and get your RegEx here
return #"^[\w-]+(\.[\w-]+)*#([a-z0-9-]+(\.[a-z0-9-]+)*?\.[a-z]{2,6}|(\d{1,3}\.){3}\d{1,3})(:\d{4})?$";
}
}
That way, you still maintain use of the built in Regex validation but you can customise it. You'd just simply use it like:
[Email(ErrorMessage = "Please use a valid email address")]
Lastly, to get to client side validation to work, you would simply add the following in your Application_Start method within Global.asax, to tell MVC to use the normal regular expression validation for this validator:
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(EmailAttribute), typeof(RegularExpressionAttributeAdapter));
Checkout ScotGu's [Email] attribute (Step 4: Creating a Custom [Email] Validation Attribute).
Do you really want to put the regex in database/config file, or do you just want to centralise them? If you just want to put the regex together, you can just define and use constants like
public class ValidationRegularExpressions {
public const string Regex1 = "...";
public const string Regex2 = "...";
}
Maybe you want to manage the regexes in external files, you can write a MSBuild task to do the replacement when you build for production.
If you REALLY want to change the validation regex at runtime, define your own ValidationAttribute, like
[RegexByKey("MyKey", ErrorMessage = "Email address is not valid")]
public string Email { get; set; }
It's just a piece of code to write:
public class RegexByKeyAttribute : ValidationAttribute {
public RegexByKey(string key) {
...
}
// override some methods
public override bool IsValid(object value) {
...
}
}
Or even just:
public class RegexByKeyAttribute : RegularExpressionAttribute {
public RegexByKey(string key) : base(LoadRegex(key)) { }
// Be careful to cache the regex is this operation is expensive.
private static string LoadRegex(string key) { ... }
}
Hope it's helpful: http://msdn.microsoft.com/en-us/library/cc668224.aspx
Why not just write you own ValidationAttribute?
http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.validationattribute.aspx
Then you can configure that thing to pull the regex from a registry setting... config file... database... etc... etc..
How to: Customize Data Field Validation in the Data Model Using Custom