does jenkins shared library groovy class support groovy trait - jenkins-pipeline

i have a shared library with a simple class that implement a simple trait,
HelloTrait.groovy :
package my.package
trait HelloTrait
{
String sayHi()
{
return "Hi!"
}
}
Test.groovy:
package my.package
class Test implements Hellotrait
{
}
jenkinsfile:
import my.package.Test
Test test = new Test();
echo test.sayHi();
but when running the pipeline jenkins throws an error
unsupported array expression

Related

Class fixture type 'SetupFixture' had one or more unresolved constructor arguments [duplicate]

I am using XUnit and need to perform some action before running a test suit. so, I try to use IClassFixture feature of XUnit. but I cannot find a way to inject dependencies into the Fixture class. my code structure is such as below:
public class MyFixture
{
IDependency _dep;
public MyFixture(IDependency dep)
{
_dep = dep;
}
void DoSomeJob()
{
//// some code there
dep.DoSome();
}
}
And this is my test class code:
public class MyTest : IClassFixture<MyFixture>
{
[Fact]
public void test_my_code()
{
////simply just test the code
}
}
but when I run the test I am getting the exception
Xunit.Sdk.TestClassException Class fixture type 'MyFixture' had one or more unresolved constructor
Your Fixture class depends on IDependency dep, which has not been configured. You could use the Fixture class to setup a service provider; However it is not the best solution, as you have to end up using service locator patter such as
serviceProvider.GetRequiredService<T>()
Suggest to use xunit.di, it is an extension built into xunit framework to support constructor dependency injection, which allows us to achieve Inversion of Control (IoC) between test classes and their dependencies.
Install-Package Xunit.Di
To use xunit.di:
Install the xunit.di nuget package
Create a Setup.cs class to configure dependencies, (optional) and inherits the Xunit.Di.Setup.cs
Configure dependencies in the Setup.cs class.
Find full instructions and demos from xunit.di GET-STARTED
Your test project has the following:
Setup class that has a public IServiceProvider, which configures all the dependencies
Test class with constructor injecting the dependencies
Your Setup.cs class looks like below:
private IServiceProvider _services;
private bool _built = false;
private readonly IHostBuilder _defaultBuilder;
public Setup()
{
_defaultBuilder = Host.CreateDefaultBuilder();
}
public IServiceProvider Services => _services ?? Build();
private IServiceProvider Build()
{
if (_built)
throw new InvalidOperationException("Build can only be called once.");
_built = true;
_defaultBuilder.ConfigureServices((context, services) =>
{
services.AddSingleton<TextReaderService>();
services.AddSingleton<IDependency, DependencyImpl>();
// where DependencyImpl implements IDependency
// ... add other services needed
});
_services = _defaultBuilder.Build().Services;
return _services;
}
Then your test class looks like below:
public class MyTest
{
private readonly IDependency _dependency;
public MyTest(IDependency dependency)
{
_dependency = dependency;
}
[Fact]
public void test_my_code()
{
var result = _dependency.DoStuff();
Assert.NotNull(result);
////simply just test the code
}
}

How do I create nested configuration parameters in a custom gradle plugin?

How do I create a nested parameter structure in a custom gradle plugin?
For starters, I am using Gradle 7.2. I want to make an expressive DSL-like structure for my plugin configuration, with a nested element
fileDiff {
file1 = file('${testFile1.getName()}')
file2 = file('${testFile2.getName()}')
messages {
message1 = 'Hi there'
}
}
While learning how to write Gradle Plugins I have been following the gradle plugin implementation docs, and they are great at showing what to do with the extension but not the "plugin" class.
So I have modeled my extension, FileDiffExtension like so
abstract class FileDiffExtension {
abstract RegularFileProperty getFile1()
abstract RegularFileProperty getFile2()
#Nested
abstract Messages getMessages()
void messages(Action<? super Messages> action) {
action.execute(getMessages())
}
}
And the nested Messages class is modeled as such
abstract class Messages {
abstract Property<String> getMessage1()
}
I think I am good up to this point. Then I need to pull my extension into my plugin and this is where I believe I am running into issues. My Plugin class currently looks like
class FileDiffPlugin implements Plugin<Project> {
#Override
void apply(Project project) {
project.tasks.register('fileDiff', FileDiffTask) {
project.extensions.create('fileDiff', FileDiffExtension)
project.fileDiff.extensions.create("messages", FileDiffExtension.messages)
file1 = project.fileDiff.file1
file2 = project.fileDiff.file2
messages = project.fileDiff.getMessages
}
}
}
I am trying to create a messages extension off of the root level extension fileDiff. Or maybe I am not supposed to set the messages object in the task to the getMessages() abstract method. But I have tried every combination I can think of. The actual task is shown below, but I don't think the problem lies here.
abstract class FileDiffTask extends DefaultTask {
#InputFile
abstract RegularFileProperty getFile1()
#InputFile
abstract RegularFileProperty getFile2()
#Input
abstract Property<Messages> getMessages()
#OutputFile
abstract RegularFileProperty getResultFile()
FileDiffTask() {
resultFile.convention(project.layout.buildDirectory.file('diff-result.txt'))
}
#TaskAction
def diff() {
// Print out the message
println messages.get().message1.toString()
// Now we do some fun file stuff
String diffResult
if (size(file1) == size(file2)) {
diffResult = "Files have the same size at ${file1.get().asFile.getBytes()} bytes}"
} else {
File largestFile = size(file1) > size(file2) ? file1.get().asFile : file2.get().asFile
diffResult = "${largestFile.toString()} is the largest file at ${largestFile.size()} bytes"
}
resultFile.get().asFile.write diffResult
println "File written to $resultFile"
println diffResult
}
private static long size(RegularFileProperty regularFileProperty) {
return regularFileProperty.get().asFile.size()
}
}
To test I am using the gradle test kit, and I'm currently getting the following error.
`
Could not create task ':fileDiff'.
No such property: messages for class: com.robschwartz.plugins.filediff.FileDiffExtension
Possible solutions: messages
`
Hm, according to docs you do not need to do anything with the sub-extension if it's marked as #Nested, it should just work. Have you tried to remove this line entirely?
project.fileDiff.extensions.create("messages", FileDiffExtension.messages)

Private method visibility confusion

I am confused with Groovy method visibility in the context of my Gradle build.
For some tests in my project, I have to first start a server.
For this I created a custom task class that extends Gradle's Test like so:
class TestWithServer extends Test {
TestWithServer() {
super()
beforeTest {
startServer()
}
}
private void startServer() {
println('placeholder')
}
}
But if I try to run such a task, I get an error:
Could not find method startServer() for arguments [] on task ':testWithServer' of type TestWithServer.
I found that when I change the visibility of startServer() to the default (public), the task runs fine.
How come I can't use the private method from within its own class?
It is not the same class, because Gradle adds some magic to the task types. Just add println this.class into the beforeTest closure to see the name of the actual class (something like TestWithServer_Decorated). This additional magic also explains why the error message contains the task name and how the class knows about being a task (type) at all. Since the decorated class is a subclass of your class you can use the protected modifier to encapsulate your method.

'Unexpected token implements` error in Angular2

Sample:
#Pipe({ name: 'values', pure: false })
export class ValuesPipe implements PipeTransform {
transform(value: any, args: any[] = null): any {
return Object.keys(value).map(key => value[key]);
}
}
It appears that class inheritance is not supported in ES6. Is there an alternative that doesn't require reverse-engineering the super class?
ES6 does have class inheritance. Classes are inherited by extends.
When you use implements you are asking for type checking against an interface. If you want type checking you should be using Typescript - if you don't need type checking then you don't need implements. Using implements doesn't have an effect on the output code — it's just for type checking during compile.
For example in typescript:
class myClass{
public myID:number
constructor(){
}
talk(){
console.log("hi there");
}
}
class newClass {
public myID:number;
talk(){
console.log("Hi from new Class");
}
}
class newClassImplements implements myClass {
public myID:number;
talk(){
console.log("Hi from new Class");
}
}
newClass and newClassImplements both result in exactly the same javascript after compilation. The version with implements just asks the compiler to make sure it has the same interface as myClass if it doesn't you get an error at compilation.
In your sample above ValuesPipe isn't inheriting from PipeTransform it's simply implementing the interface. If you don't need the type checking you should be able to just write the function you want and forget about implementing the interface.

Dependency injection in TypeScript

I'm looking into the possibilities to do TDD with TypeScript.
If I write my tests in TypeScript, is it possible to make the import statements return mocks for my class under test?
Or is the only feasible approach to write the tests in pure javascript and deal with injecting AMDs myself?
I have developed an IoC container called InversifyJS with advanced dependency injection features like contextual bindings.
You need to follow 3 basic steps to use it:
1. Add annotations
The annotation API is based on Angular 2.0:
import { injectable, inject } from "inversify";
#injectable()
class Katana implements IKatana {
public hit() {
return "cut!";
}
}
#injectable()
class Shuriken implements IShuriken {
public throw() {
return "hit!";
}
}
#injectable()
class Ninja implements INinja {
private _katana: IKatana;
private _shuriken: IShuriken;
public constructor(
#inject("IKatana") katana: IKatana,
#inject("IShuriken") shuriken: IShuriken
) {
this._katana = katana;
this._shuriken = shuriken;
}
public fight() { return this._katana.hit(); };
public sneak() { return this._shuriken.throw(); };
}
2. Declare bindings
The binding API is based on Ninject:
import { Kernel } from "inversify";
import { Ninja } from "./entities/ninja";
import { Katana } from "./entities/katana";
import { Shuriken} from "./entities/shuriken";
var kernel = new Kernel();
kernel.bind<INinja>("INinja").to(Ninja);
kernel.bind<IKatana>("IKatana").to(Katana);
kernel.bind<IShuriken>("IShuriken").to(Shuriken);
export default kernel;
3. Resolve dependencies
The resolution API is based on Ninject:
import kernel = from "./inversify.config";
var ninja = kernel.get<INinja>("INinja");
expect(ninja.fight()).eql("cut!"); // true
expect(ninja.sneak()).eql("hit!"); // true
The latest release (2.0.0) supports many use cases:
Kernel modules
Kernel middleware
Use classes, string literals or Symbols as dependency identifiers
Injection of constant values
Injection of class constructors
Injection of factories
Auto factory
Injection of providers (async factory)
Activation handlers (used to inject proxies)
Multi injections
Tagged bindings
Custom tag decorators
Named bindings
Contextual bindings
Friendly exceptions (e.g. Circular dependencies)
You can learn more about it at https://github.com/inversify/InversifyJS
I use infuse.js for Dependency Injection in TypeScript.
Reference the d.ts
/// <reference path="definition/infusejs/infusejs.d.ts"/>
Initialize your injector at startup
this.injector = new infuse.Injector();
Map Dependencies
this.injector.mapClass( 'TodoController', TodoController );
this.injector.mapClass( 'TodoView', TodoView );
this.injector.mapClass( 'TodoModel', TodoModel, true ); // 'true' Map as singleton
Inject Dependencies
export class TodoController
{
static inject = ['TodoView', 'TodoModel'];
constructor( todoView:TodoView, todoModel:TodoModel )
{
}
}
It's string based as opposed to being type based (as reflection isn't yet possible in TypeScript). Despite that, it works very well in my applications.
Try this Dependency Injector (Typejector)
GitHub Typejector
With new TypeScript 1.5 it is possible using annotation way
For example
#injection
class SingletonClass {
public cat: string = "Kitty";
public dog: string = "Hot";
public say() {
alert(`${this.cat}-Cat and ${this.dog}-Dog`);
}
}
#injection
class SimpleClass {
public say(something: string) {
alert(`You said ${something}?`);
}
}
#resolve
class NeedInjectionsClass {
#inject(SingletonClass)
public helper: SingletonClass;
#inject(SimpleClass)
public simpleHelper: SimpleClass;
constructor() {
this.helper.say();
this.simpleHelper.say("wow");
}
}
class ChildClass extends NeedInjectionsClass {
}
var needInjection = new ChildClass();
For question case:
some property should realise pseudo Interface (or abstract class) like in next example.
class InterfaceClass {
public cat: string;
public dog: string;
public say() {
}
}
#injection(true, InterfaceClass)
class SingletonClass extends InterfaceClass {
public cat: string = "Kitty";
public dog: string = "Hot";
public say() {
alert(`${this.cat}-Cat and ${this.dog}-Dog`);
}
}
#injection(true, InterfaceClass)
class MockInterfaceClass extends InterfaceClass {
public cat: string = "Kitty";
public dog: string = "Hot";
public say() {
alert(`Mock-${this.cat}-Cat and Mock-${this.dog}-Dog`);
}
}
#injection
class SimpleClass {
public say(something: string) {
alert(`You said ${something}?`);
}
}
#resolve
class NeedInjectionsClass {
#inject(InterfaceClass)
public helper: InterfaceClass;
#inject(SimpleClass)
public simpleHelper: SimpleClass;
constructor() {
this.helper.say();
this.simpleHelper.say("wow");
}
}
class ChildClass extends NeedInjectionsClass {
}
var needInjection = new ChildClass();
Note: Mock injection should define after source code, because it mast redefine class-creator for interface
For people who use Angular2 I have developed Fluency Injection https://www.npmjs.com/package/fluency-injection. The documentation is quite complete and it mimics the behaviour of Angular2's DI.
Feedback is much appreciated and I hope it helps you :)
You can use the solution:
Lightweight dependency injection container for JavaScript/TypeScript
import {autoInjectable, container} from "tsyringe";
class MyService {
move(){
console.log('myService move 123', );
}
}
class MyServiceMock {
move(){
console.log('mock myService move 777', );
}
}
#autoInjectable()
export class ClassA {
constructor(public service?: MyService) {
}
move(){
this.service?.move();
}
}
container.register(MyService, {
useClass: MyServiceMock
});
new ClassA().move();
output:
mock myService move 777
I've been developing a DI solution called Pigly. An example given the original question regarding injecting and testing (admittedly not automatic-mock generation - although you could try ts-auto-mock as I've done here):
Given:
interface IDb {
set(key: string, value: string);
}
interface IApi {
setName(name: string);
}
class Api implements IApi {
constructor(private db: IDb) {}
setName(name: string){
this.db.set("name", name);
}
}
We can bind the types with,
import { Kernel, toSelf, to, toConst } from 'pigly';
import * as sinon from 'sinon';
let spy = sinon.spy();
let kernel = new Kernel();
kernel.bind(toSelf(Api));
kernel.bind<IApi>(to<Api>());
kernel.bind<IDb>(toConst({ set: spy }));
then resolve and test with:
let api = kernel.get<IApi>();
api.setName("John");
console.log(spy.calledWith("name", "John"));
execution/compilation of this example requires a typescript transformer - to compile the interface-symbols and constructor provider into plain javascript. There are a few ways to do this. The ts-node + ttypescript approach is to have a tsconfig.json:
{
"compilerOptions": {
"target": "es2015",
"module": "commonjs",
"moduleResolution": "node",
"plugins": [{
"transform": "#pigly/transformer"
}]
}
}
and execute with
ts-node --compiler ttypescript example-mock.ts
Pigly has the distinction of not requiring any changes to your (or third-party) classes, at the expense of either the use of a typescript transformer, or more verbose binding if (you don't want to use the transformer). Its still experimental, but I think it shows promise.
TypeScript works well with AMD loaders like requirejs. If confgured properly, TypeScript will output fully AMD compliant javascript.
In a testing situation, you could configure requirejs to inject testable modules.
You can give this a shot: https://www.npmjs.com/package/easy-injectionjs. It is a generic use dependency injection package.
#EasySingleton creates a single instance of the dependency through the entire application. It is ideal for a service of some sort.
#EasyPrototype creates as many instances of the dependency as needed. It is ideal for changeable dependencies.
#EasyFactory is primarily used for inheritance:
You can do anything using this package:
Simple usage (Coming from the readme):
import { Easy, EasyFactory, EasyPrototype, EasySingleton } from 'easy-injectionjs';
#EasyFactory()
abstract class Person {
abstract getName();
abstract setName(v: string);
}
// #EasyObservable()
#EasySingleton()
class Somebody extends Person{
// #Easy()
constructor (private name: string) {
super()
this.name = 'Sal';
}
public getName() {
return this.name;
}
public setName(v: string) {
this.name = v;
}
}
#EasyPrototype()
class Nobody extends Person{
#Easy()
somebody: Person;
constructor () {
super()
}
public getName() {
return this.somebody.getName();
}
public setName(v: string) {
this.somebody.setName(v);
}
}
#EasyPrototype()
class Data {
#Easy()
somebody: Person;
name: string;
change(v: string) {
this.somebody.setName(v);
}
getName(): string {
return this.somebody.getName();
}
}
let n = new Nobody();
console.log(n.getName()) // Prints Sal
n.setName('awesome');
console.log(n.getName()) // Prints awesome
let d = new Data()
console.log(d.getName()) // Prints awesome
d.change('Gelba')
console.log(n.getName()) // Prints Gelba
d.change('kaa')
console.log(n.getName()) // Prints Kaa
Even if you want to inject node modules you can do this:
import * as IExpress from 'express';
import { Easy, EasySingleton } from 'easy-injectionjs';
#EasySingleton()
class Express extends IExpress {}
#EasySingleton()
export class App {
#Easy()
private _express: Express;
}
let app = new App();
console.log(app)
Of course, the usage of the express server isn't for console logging. It is just for testing :D.
Hope that helps :D
Dime is a very simple dependency injection library. It's very early into development, though, so it probably has some bugs. There is more information on the wiki page.
Example usage:
import { ItemsService } from './items-service'; // ItemsService is an interface
import { Inject } from '#coined/dime';
class ItemsWidget {
#Inject()
private itemsService: ItemsService;
render() {
this.itemsService.getItems().subscribe(items => {
// ...
});
}
}
// Setup
const appPackage = new Package("App", {
token: "itemsService",
provideClass: AmazonItemsService // AmazonItemsService implements ItemsService
});
Dime.mountPackages(appPackage);
// Display the widget
const widget = new ItemsWidget();
widget.render();
I work on AutoFixtureTS that is inspired by AutoFixture. AutoFixtureTS makes it easier for TypeScript developers to do Test-Driven Development by automating non-relevant Test Fixture Setup, allowing the Test Developer to focus on the essentials of each test case.
http://ronniehegelund.github.io/AutoFixtureTS/
Its still just prototype code, but check it out :-)
/ronnie

Resources